claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -0
- claude_mpm/VERSION +1 -0
- claude_mpm/__init__.py +50 -12
- claude_mpm/__main__.py +7 -2
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
- claude_mpm/agents/MEMORY.md +72 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
- claude_mpm/agents/WORKFLOW.md +111 -0
- claude_mpm/agents/__init__.py +92 -80
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +560 -745
- claude_mpm/agents/agent_loader_integration.py +53 -55
- claude_mpm/agents/agents_metadata.py +186 -27
- claude_mpm/agents/async_agent_loader.py +436 -0
- claude_mpm/agents/base_agent.json +8 -4
- claude_mpm/agents/frontmatter_validator.py +754 -0
- claude_mpm/agents/system_agent_config.py +222 -155
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/__init__.py +17 -13
- claude_mpm/agents/templates/circuit-breakers.md +1391 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +90 -128
- claude_mpm/cli/__main__.py +33 -0
- claude_mpm/cli/chrome_devtools_installer.py +175 -0
- claude_mpm/cli/commands/__init__.py +36 -12
- claude_mpm/cli/commands/agent_manager.py +1403 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +335 -0
- claude_mpm/cli/commands/agents.py +2503 -168
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +540 -0
- claude_mpm/cli/commands/analyze.py +553 -0
- claude_mpm/cli/commands/analyze_code.py +528 -0
- claude_mpm/cli/commands/auto_configure.py +1053 -0
- claude_mpm/cli/commands/cleanup.py +588 -0
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
- claude_mpm/cli/commands/config.py +586 -0
- claude_mpm/cli/commands/configure.py +2654 -0
- claude_mpm/cli/commands/configure_agent_display.py +282 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +286 -0
- claude_mpm/cli/commands/debug.py +1386 -0
- claude_mpm/cli/commands/doctor.py +243 -0
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +195 -74
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +205 -0
- claude_mpm/cli/commands/mcp_command_router.py +161 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +346 -0
- claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
- claude_mpm/cli/commands/mcp_server_commands.py +155 -0
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +585 -846
- claude_mpm/cli/commands/monitor.py +228 -310
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +759 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +195 -0
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +910 -488
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1246 -0
- claude_mpm/cli/commands/summarize.py +413 -0
- claude_mpm/cli/commands/tickets.py +536 -53
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +297 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1947 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +87 -563
- claude_mpm/cli/parsers/__init__.py +35 -0
- claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +575 -0
- claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
- claude_mpm/cli/parsers/analyze_parser.py +135 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
- claude_mpm/cli/parsers/base_parser.py +644 -0
- claude_mpm/cli/parsers/config_parser.py +208 -0
- claude_mpm/cli/parsers/configure_parser.py +138 -0
- claude_mpm/cli/parsers/dashboard_parser.py +113 -0
- claude_mpm/cli/parsers/debug_parser.py +319 -0
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +195 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +142 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +157 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +277 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/shared/__init__.py +40 -0
- claude_mpm/cli/shared/argument_patterns.py +205 -0
- claude_mpm/cli/shared/base_command.py +242 -0
- claude_mpm/cli/shared/error_handling.py +242 -0
- claude_mpm/cli/shared/output_formatters.py +241 -0
- claude_mpm/cli/startup.py +1743 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +839 -0
- claude_mpm/cli/utils.py +136 -47
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +42 -64
- claude_mpm/commands/__init__.py +14 -0
- claude_mpm/commands/mpm-config.md +28 -0
- claude_mpm/commands/mpm-doctor.md +20 -0
- claude_mpm/commands/mpm-help.md +20 -0
- claude_mpm/commands/mpm-init.md +120 -0
- claude_mpm/commands/mpm-monitor.md +31 -0
- claude_mpm/commands/mpm-organize.md +120 -0
- claude_mpm/commands/mpm-postmortem.md +21 -0
- claude_mpm/commands/mpm-session-resume.md +30 -0
- claude_mpm/commands/mpm-status.md +20 -0
- claude_mpm/commands/mpm-ticket-view.md +109 -0
- claude_mpm/commands/mpm-version.md +20 -0
- claude_mpm/commands/mpm.md +31 -0
- claude_mpm/config/__init__.py +42 -2
- claude_mpm/config/agent_config.py +402 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +352 -0
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +258 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +125 -83
- claude_mpm/constants.py +132 -22
- claude_mpm/core/__init__.py +62 -36
- claude_mpm/core/agent_name_normalizer.py +71 -73
- claude_mpm/core/agent_registry.py +385 -492
- claude_mpm/core/agent_session_manager.py +81 -70
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +159 -122
- claude_mpm/core/cache.py +560 -0
- claude_mpm/core/claude_runner.py +696 -916
- claude_mpm/core/config.py +613 -122
- claude_mpm/core/config_aliases.py +74 -73
- claude_mpm/core/config_constants.py +314 -0
- claude_mpm/core/constants.py +361 -0
- claude_mpm/core/container.py +646 -104
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/exceptions.py +536 -0
- claude_mpm/core/factories.py +105 -109
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +278 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +213 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +485 -414
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +246 -86
- claude_mpm/core/hook_performance_config.py +147 -0
- claude_mpm/core/injectable_service.py +72 -63
- claude_mpm/core/instruction_reinforcement_hook.py +267 -0
- claude_mpm/core/interactive_session.py +670 -0
- claude_mpm/core/interfaces.py +570 -164
- claude_mpm/core/lazy.py +467 -0
- claude_mpm/core/log_manager.py +707 -0
- claude_mpm/core/logger.py +295 -134
- claude_mpm/core/logging_config.py +474 -0
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/minimal_framework_loader.py +24 -22
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +594 -0
- claude_mpm/core/optimized_agent_loader.py +479 -0
- claude_mpm/core/optimized_startup.py +554 -0
- claude_mpm/core/output_style_manager.py +483 -0
- claude_mpm/core/pm_hook_interceptor.py +197 -82
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +153 -116
- claude_mpm/core/session_manager.py +179 -64
- claude_mpm/core/shared/__init__.py +17 -0
- claude_mpm/core/shared/config_loader.py +326 -0
- claude_mpm/core/shared/path_resolver.py +281 -0
- claude_mpm/core/shared/singleton_manager.py +221 -0
- claude_mpm/core/socketio_pool.py +400 -137
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +64 -57
- claude_mpm/core/types.py +307 -0
- claude_mpm/core/typing_utils.py +553 -0
- claude_mpm/core/unified_agent_registry.py +969 -0
- claude_mpm/core/unified_config.py +570 -0
- claude_mpm/core/unified_paths.py +941 -0
- claude_mpm/dashboard/__init__.py +12 -0
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/__init__.py +10 -0
- claude_mpm/experimental/cli_enhancements.py +104 -89
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +76 -66
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +37 -32
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
- claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
- claude_mpm/hooks/claude_hooks/installer.py +806 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
- claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +201 -107
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +92 -76
- claude_mpm/hooks/validation_hooks.py +62 -54
- claude_mpm/init.py +518 -83
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +40 -23
- claude_mpm/models/agent_session.py +538 -0
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/schemas/__init__.py +12 -0
- claude_mpm/scripts/__init__.py +15 -0
- claude_mpm/scripts/claude-hook-handler.sh +227 -0
- claude_mpm/scripts/launch_monitor.py +165 -0
- claude_mpm/scripts/mpm_doctor.py +322 -0
- claude_mpm/scripts/socketio_daemon.py +189 -200
- claude_mpm/scripts/start_activity_logging.py +91 -0
- claude_mpm/services/__init__.py +208 -39
- claude_mpm/services/agent_capabilities_service.py +266 -0
- claude_mpm/services/agents/__init__.py +89 -0
- claude_mpm/services/agents/agent_builder.py +514 -0
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_recommendation_service.py +278 -0
- claude_mpm/services/agents/agent_review_service.py +280 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
- claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
- claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
- claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
- claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
- claude_mpm/services/agents/deployment/agent_validator.py +376 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
- claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
- claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
- claude_mpm/services/agents/git_source_manager.py +682 -0
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
- claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
- claude_mpm/services/agents/memory/__init__.py +22 -0
- claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
- claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
- claude_mpm/services/agents/memory/content_manager.py +470 -0
- claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
- claude_mpm/services/agents/memory/memory_file_service.py +129 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
- claude_mpm/services/agents/memory/template_generator.py +83 -0
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +617 -0
- claude_mpm/services/agents/registry/__init__.py +30 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
- claude_mpm/services/agents/startup_sync.py +259 -0
- claude_mpm/services/agents/toolchain_detector.py +478 -0
- claude_mpm/services/analysis/__init__.py +35 -0
- claude_mpm/services/analysis/clone_detector.py +1030 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +665 -0
- claude_mpm/services/claude_session_logger.py +321 -0
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +408 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +590 -0
- claude_mpm/services/cli/memory_crud_service.py +622 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +604 -0
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +362 -0
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +446 -0
- claude_mpm/services/command_handler_service.py +221 -0
- claude_mpm/services/communication/__init__.py +22 -0
- claude_mpm/services/core/__init__.py +108 -0
- claude_mpm/services/core/base.py +269 -0
- claude_mpm/services/core/cache_manager.py +309 -0
- claude_mpm/services/core/interfaces/__init__.py +273 -0
- claude_mpm/services/core/interfaces/agent.py +514 -0
- claude_mpm/services/core/interfaces/communication.py +316 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/infrastructure.py +357 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/service.py +405 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +81 -0
- claude_mpm/services/core/memory_manager.py +682 -0
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +517 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +38 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/base_check.py +60 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
- claude_mpm/services/diagnostics/models.py +138 -0
- claude_mpm/services/event_aggregator.py +582 -0
- claude_mpm/services/event_bus/__init__.py +18 -0
- claude_mpm/services/event_bus/config.py +186 -0
- claude_mpm/services/event_bus/direct_relay.py +312 -0
- claude_mpm/services/event_bus/event_bus.py +396 -0
- claude_mpm/services/event_bus/relay.py +326 -0
- claude_mpm/services/events/__init__.py +44 -0
- claude_mpm/services/events/consumers/__init__.py +18 -0
- claude_mpm/services/events/consumers/dead_letter.py +306 -0
- claude_mpm/services/events/consumers/logging.py +184 -0
- claude_mpm/services/events/consumers/metrics.py +241 -0
- claude_mpm/services/events/consumers/socketio.py +377 -0
- claude_mpm/services/events/core.py +480 -0
- claude_mpm/services/events/interfaces.py +214 -0
- claude_mpm/services/events/producers/__init__.py +14 -0
- claude_mpm/services/events/producers/hook.py +269 -0
- claude_mpm/services/events/producers/system.py +329 -0
- claude_mpm/services/exceptions.py +433 -353
- claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
- claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +579 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +159 -111
- claude_mpm/services/infrastructure/__init__.py +52 -0
- claude_mpm/services/infrastructure/context_preservation.py +569 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +209 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
- claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
- claude_mpm/services/infrastructure/monitoring/base.py +122 -0
- claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
- claude_mpm/services/infrastructure/monitoring/network.py +219 -0
- claude_mpm/services/infrastructure/monitoring/process.py +343 -0
- claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
- claude_mpm/services/infrastructure/monitoring/service.py +368 -0
- claude_mpm/services/infrastructure/monitoring.py +71 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/__init__.py +19 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
- claude_mpm/services/memory/cache/simple_cache.py +331 -0
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +648 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
- claude_mpm/services/memory/router.py +951 -0
- claude_mpm/services/memory_hook_service.py +470 -0
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +698 -0
- claude_mpm/services/monitor/daemon_manager.py +1076 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +730 -0
- claude_mpm/services/monitor/server.py +1493 -0
- claude_mpm/services/monitor_build_service.py +349 -0
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/pm_skills_deployer.py +707 -0
- claude_mpm/services/port_manager.py +597 -0
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/project/__init__.py +44 -0
- claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
- claude_mpm/services/project/analyzer_v2.py +566 -0
- claude_mpm/services/project/architecture_analyzer.py +461 -0
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +462 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/language_analyzer.py +265 -0
- claude_mpm/services/project/metrics_collector.py +407 -0
- claude_mpm/services/project/project_organizer.py +1009 -0
- claude_mpm/services/project/registry.py +636 -0
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/recovery_manager.py +293 -240
- claude_mpm/services/response_tracker.py +267 -0
- claude_mpm/services/runner_configuration_service.py +605 -0
- claude_mpm/services/self_upgrade_service.py +608 -0
- claude_mpm/services/session_management_service.py +314 -0
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +21 -0
- claude_mpm/services/shared/async_service_base.py +216 -0
- claude_mpm/services/shared/config_service_base.py +301 -0
- claude_mpm/services/shared/lifecycle_service_base.py +308 -0
- claude_mpm/services/shared/manager_base.py +315 -0
- claude_mpm/services/shared/service_factory.py +309 -0
- claude_mpm/services/skills/__init__.py +21 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
- claude_mpm/services/skills/selective_skill_deployer.py +744 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +1168 -0
- claude_mpm/services/socketio/__init__.py +25 -0
- claude_mpm/services/socketio/client_proxy.py +229 -0
- claude_mpm/services/socketio/dashboard_server.py +362 -0
- claude_mpm/services/socketio/event_normalizer.py +798 -0
- claude_mpm/services/socketio/handlers/__init__.py +30 -0
- claude_mpm/services/socketio/handlers/base.py +136 -0
- claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
- claude_mpm/services/socketio/handlers/connection.py +643 -0
- claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
- claude_mpm/services/socketio/handlers/file.py +263 -0
- claude_mpm/services/socketio/handlers/git.py +962 -0
- claude_mpm/services/socketio/handlers/hook.py +211 -0
- claude_mpm/services/socketio/handlers/memory.py +26 -0
- claude_mpm/services/socketio/handlers/project.py +24 -0
- claude_mpm/services/socketio/handlers/registry.py +214 -0
- claude_mpm/services/socketio/migration_utils.py +343 -0
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +569 -0
- claude_mpm/services/socketio/server/connection_manager.py +579 -0
- claude_mpm/services/socketio/server/core.py +1079 -0
- claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
- claude_mpm/services/socketio/server/main.py +501 -0
- claude_mpm/services/socketio_client_manager.py +173 -143
- claude_mpm/services/socketio_server.py +38 -1657
- claude_mpm/services/subprocess_launcher_service.py +322 -0
- claude_mpm/services/system_instructions_service.py +270 -0
- claude_mpm/services/ticket_manager.py +25 -209
- claude_mpm/services/ticket_services/__init__.py +26 -0
- claude_mpm/services/ticket_services/crud_service.py +328 -0
- claude_mpm/services/ticket_services/formatter_service.py +290 -0
- claude_mpm/services/ticket_services/search_service.py +324 -0
- claude_mpm/services/ticket_services/validation_service.py +303 -0
- claude_mpm/services/ticket_services/workflow_service.py +244 -0
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +280 -0
- claude_mpm/services/version_control/__init__.py +34 -37
- claude_mpm/services/version_control/branch_strategy.py +26 -17
- claude_mpm/services/version_control/conflict_resolution.py +52 -36
- claude_mpm/services/version_control/git_operations.py +183 -49
- claude_mpm/services/version_control/semantic_versioning.py +172 -61
- claude_mpm/services/version_control/version_parser.py +546 -0
- claude_mpm/services/version_service.py +379 -0
- claude_mpm/services/visualization/__init__.py +15 -0
- claude_mpm/services/visualization/mermaid_generator.py +937 -0
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +439 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +405 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +546 -0
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/tools/__init__.py +10 -0
- claude_mpm/tools/__main__.py +208 -0
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +631 -0
- claude_mpm/tools/code_tree_events.py +420 -0
- claude_mpm/tools/socketio_debug.py +671 -0
- claude_mpm/utils/__init__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +1090 -0
- claude_mpm/utils/agent_filters.py +261 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +168 -126
- claude_mpm/utils/console.py +11 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +373 -0
- claude_mpm/utils/dependency_manager.py +60 -59
- claude_mpm/utils/dependency_strategies.py +381 -0
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +313 -0
- claude_mpm/utils/error_handler.py +78 -66
- claude_mpm/utils/file_utils.py +305 -0
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +244 -0
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +110 -104
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +823 -0
- claude_mpm/utils/session_logging.py +121 -0
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +343 -0
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +214 -108
- claude_mpm/validation/frontmatter_validator.py +252 -0
- claude_mpm-5.4.55.dist-info/METADATA +999 -0
- claude_mpm-5.4.55.dist-info/RECORD +868 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
- claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
- claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
- claude_mpm/agents/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
- claude_mpm/agents/base_agent_loader.py +0 -529
- claude_mpm/agents/schema/agent_schema.json +0 -314
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
- claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
- claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
- claude_mpm/agents/templates/data_engineer.json +0 -110
- claude_mpm/agents/templates/documentation.json +0 -109
- claude_mpm/agents/templates/engineer.json +0 -113
- claude_mpm/agents/templates/ops.json +0 -109
- claude_mpm/agents/templates/pm.json +0 -25
- claude_mpm/agents/templates/qa.json +0 -111
- claude_mpm/agents/templates/research.json +0 -65
- claude_mpm/agents/templates/security.json +0 -113
- claude_mpm/agents/templates/test_integration.json +0 -112
- claude_mpm/agents/templates/version_control.json +0 -107
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/dashboard/open_dashboard.py +0 -34
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/agent_deployment.py +0 -1534
- claude_mpm/services/agent_lifecycle_manager.py +0 -1169
- claude_mpm/services/agent_memory_manager.py +0 -1415
- claude_mpm/services/agent_registry.py +0 -676
- claude_mpm/services/deployed_agent_discovery.py +0 -226
- claude_mpm/services/framework_agent_loader.py +0 -337
- claude_mpm/services/framework_claude_md_generator.py +0 -621
- claude_mpm/services/health_monitor.py +0 -892
- claude_mpm/services/memory_router.py +0 -538
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -508
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- claude_mpm/utils/paths.py +0 -289
- claude_mpm-3.4.10.dist-info/METADATA +0 -183
- claude_mpm-3.4.10.dist-info/RECORD +0 -201
- claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
claude_mpm/cli/commands/run.py
CHANGED
|
@@ -1,119 +1,152 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
1
3
|
"""
|
|
2
4
|
Run command implementation for claude-mpm.
|
|
3
5
|
|
|
4
6
|
WHY: This module handles the main 'run' command which starts Claude sessions.
|
|
5
7
|
It's the most commonly used command and handles both interactive and non-interactive modes.
|
|
8
|
+
|
|
9
|
+
DESIGN DECISIONS:
|
|
10
|
+
- Use BaseCommand for consistent CLI patterns
|
|
11
|
+
- Leverage shared utilities for argument parsing and output formatting
|
|
12
|
+
- Maintain backward compatibility with existing functionality
|
|
13
|
+
- Support multiple output formats (json, yaml, table, text)
|
|
6
14
|
"""
|
|
7
15
|
|
|
8
|
-
import os
|
|
9
16
|
import subprocess
|
|
10
17
|
import sys
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
from pathlib import Path
|
|
14
|
-
from datetime import datetime
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
|
+
from typing import Optional
|
|
15
20
|
|
|
16
|
-
from ...core.logger import get_logger
|
|
17
21
|
from ...constants import LogLevel
|
|
18
|
-
from
|
|
19
|
-
from ...
|
|
20
|
-
from ...
|
|
22
|
+
from ...core.logger import get_logger
|
|
23
|
+
from ...core.unified_paths import get_scripts_dir
|
|
24
|
+
from ...services.cli.session_manager import SessionManager
|
|
25
|
+
|
|
26
|
+
# SocketIOManager functionality now provided by UnifiedDashboardManager
|
|
27
|
+
from ...services.cli.startup_checker import StartupCheckerService
|
|
28
|
+
from ...services.cli.unified_dashboard_manager import UnifiedDashboardManager
|
|
29
|
+
from ..shared import BaseCommand, CommandResult
|
|
30
|
+
from ..startup_logging import (
|
|
31
|
+
cleanup_old_startup_logs,
|
|
32
|
+
log_startup_status,
|
|
33
|
+
setup_startup_logging,
|
|
34
|
+
)
|
|
35
|
+
from ..utils import get_user_input
|
|
21
36
|
|
|
22
37
|
|
|
23
38
|
def filter_claude_mpm_args(claude_args):
|
|
24
39
|
"""
|
|
25
40
|
Filter out claude-mpm specific arguments from claude_args before passing to Claude CLI.
|
|
26
|
-
|
|
41
|
+
|
|
27
42
|
WHY: The argparse.REMAINDER captures ALL remaining arguments, including claude-mpm
|
|
28
43
|
specific flags like --monitor, etc. Claude CLI doesn't understand these
|
|
29
44
|
flags and will error if they're passed through.
|
|
30
|
-
|
|
45
|
+
|
|
31
46
|
DESIGN DECISION: We maintain a list of known claude-mpm flags to filter out,
|
|
32
|
-
ensuring only genuine Claude CLI arguments are passed through.
|
|
33
|
-
|
|
47
|
+
ensuring only genuine Claude CLI arguments are passed through. We also remove
|
|
48
|
+
the '--' separator that argparse uses, as it's not needed by Claude CLI.
|
|
49
|
+
|
|
34
50
|
Args:
|
|
35
51
|
claude_args: List of arguments captured by argparse.REMAINDER
|
|
36
|
-
|
|
52
|
+
|
|
37
53
|
Returns:
|
|
38
54
|
Filtered list of arguments safe to pass to Claude CLI
|
|
39
55
|
"""
|
|
40
56
|
if not claude_args:
|
|
41
57
|
return []
|
|
42
|
-
|
|
58
|
+
|
|
43
59
|
# Known claude-mpm specific flags that should NOT be passed to Claude CLI
|
|
44
60
|
# This includes all MPM-specific arguments from the parser
|
|
45
61
|
mpm_flags = {
|
|
46
62
|
# Run-specific flags
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
"--monitor",
|
|
64
|
+
"--websocket-port",
|
|
65
|
+
"--no-hooks",
|
|
66
|
+
"--no-tickets",
|
|
67
|
+
"--intercept-commands",
|
|
68
|
+
"--no-native-agents",
|
|
69
|
+
"--launch-method",
|
|
70
|
+
"--mpm-resume",
|
|
71
|
+
"--reload-agents", # New flag to force rebuild system agents
|
|
72
|
+
# Dependency checking flags (MPM-specific)
|
|
73
|
+
"--no-check-dependencies",
|
|
74
|
+
"--force-check-dependencies",
|
|
75
|
+
"--no-prompt",
|
|
76
|
+
"--force-prompt",
|
|
55
77
|
# Input/output flags (these are MPM-specific, not Claude CLI flags)
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
"--input",
|
|
79
|
+
"--non-interactive",
|
|
58
80
|
# Common logging flags (these are MPM-specific, not Claude CLI flags)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
81
|
+
"--debug",
|
|
82
|
+
"--logging",
|
|
83
|
+
"--log-dir",
|
|
62
84
|
# Framework flags (these are MPM-specific)
|
|
63
|
-
|
|
64
|
-
|
|
85
|
+
"--framework-path",
|
|
86
|
+
"--agents-dir",
|
|
65
87
|
# Version flag (handled by MPM)
|
|
66
|
-
|
|
88
|
+
"--version",
|
|
67
89
|
# Short flags (MPM-specific equivalents)
|
|
68
|
-
|
|
69
|
-
|
|
90
|
+
"-i", # --input (MPM-specific, not Claude CLI)
|
|
91
|
+
"-d", # --debug (MPM-specific, not Claude CLI)
|
|
70
92
|
}
|
|
71
|
-
|
|
93
|
+
|
|
72
94
|
filtered_args = []
|
|
73
95
|
i = 0
|
|
74
96
|
while i < len(claude_args):
|
|
75
97
|
arg = claude_args[i]
|
|
76
|
-
|
|
98
|
+
|
|
99
|
+
# Skip the '--' separator used by argparse - Claude doesn't need it
|
|
100
|
+
if arg == "--":
|
|
101
|
+
i += 1
|
|
102
|
+
continue
|
|
103
|
+
|
|
77
104
|
# Check if this is a claude-mpm flag
|
|
78
105
|
if arg in mpm_flags:
|
|
79
106
|
# Skip this flag
|
|
80
107
|
i += 1
|
|
81
108
|
# Also skip the next argument if this flag expects a value
|
|
82
109
|
value_expecting_flags = {
|
|
83
|
-
|
|
84
|
-
|
|
110
|
+
"--websocket-port",
|
|
111
|
+
"--launch-method",
|
|
112
|
+
"--logging",
|
|
113
|
+
"--log-dir",
|
|
114
|
+
"--framework-path",
|
|
115
|
+
"--agents-dir",
|
|
116
|
+
"-i",
|
|
117
|
+
"--input",
|
|
85
118
|
}
|
|
86
119
|
optional_value_flags = {
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
120
|
+
"--mpm-resume"
|
|
121
|
+
} # These flags can have optional values (nargs="?")
|
|
122
|
+
|
|
90
123
|
if arg in value_expecting_flags and i < len(claude_args):
|
|
91
124
|
i += 1 # Skip the value too
|
|
92
125
|
elif arg in optional_value_flags and i < len(claude_args):
|
|
93
126
|
# For optional value flags, only skip next arg if it doesn't start with --
|
|
94
127
|
next_arg = claude_args[i]
|
|
95
|
-
if not next_arg.startswith(
|
|
128
|
+
if not next_arg.startswith("--"):
|
|
96
129
|
i += 1 # Skip the value
|
|
97
130
|
else:
|
|
98
131
|
# This is not a claude-mpm flag, keep it
|
|
99
132
|
filtered_args.append(arg)
|
|
100
133
|
i += 1
|
|
101
|
-
|
|
134
|
+
|
|
102
135
|
return filtered_args
|
|
103
136
|
|
|
104
137
|
|
|
105
138
|
def create_session_context(session_id, session_manager):
|
|
106
139
|
"""
|
|
107
140
|
Create enhanced context for resumed sessions.
|
|
108
|
-
|
|
141
|
+
|
|
109
142
|
WHY: When resuming a session, we want to provide Claude with context about
|
|
110
143
|
the previous session including what agents were used and when it was created.
|
|
111
144
|
This helps maintain continuity across session boundaries.
|
|
112
|
-
|
|
145
|
+
|
|
113
146
|
Args:
|
|
114
147
|
session_id: Session ID being resumed
|
|
115
148
|
session_manager: SessionManager instance
|
|
116
|
-
|
|
149
|
+
|
|
117
150
|
Returns:
|
|
118
151
|
Enhanced context string with session information
|
|
119
152
|
"""
|
|
@@ -121,193 +154,884 @@ def create_session_context(session_id, session_manager):
|
|
|
121
154
|
from ...core.claude_runner import create_simple_context
|
|
122
155
|
except ImportError:
|
|
123
156
|
from claude_mpm.core.claude_runner import create_simple_context
|
|
124
|
-
|
|
157
|
+
|
|
125
158
|
base_context = create_simple_context()
|
|
126
|
-
|
|
127
|
-
session_data = session_manager.
|
|
159
|
+
|
|
160
|
+
session_data = session_manager.get_session_info(session_id)
|
|
128
161
|
if not session_data:
|
|
129
162
|
return base_context
|
|
130
|
-
|
|
163
|
+
|
|
131
164
|
# Add session resumption information
|
|
132
165
|
session_info = f"""
|
|
133
166
|
|
|
134
167
|
# Session Resumption
|
|
135
168
|
|
|
136
169
|
You are resuming session {session_id[:8]}... which was:
|
|
137
|
-
- Created: {session_data.get(
|
|
138
|
-
- Last used: {session_data.get(
|
|
139
|
-
- Context: {session_data.get(
|
|
140
|
-
- Use count: {session_data.get(
|
|
170
|
+
- Created: {session_data.get("created_at", "unknown")}
|
|
171
|
+
- Last used: {session_data.get("last_used", "unknown")}
|
|
172
|
+
- Context: {session_data.get("context", "default")}
|
|
173
|
+
- Use count: {session_data.get("use_count", 0)}
|
|
141
174
|
"""
|
|
142
|
-
|
|
175
|
+
|
|
143
176
|
# Add information about agents previously run in this session
|
|
144
|
-
agents_run = session_data.get(
|
|
177
|
+
agents_run = session_data.get("agents_run", [])
|
|
145
178
|
if agents_run:
|
|
146
179
|
session_info += "\n- Previous agent activity:\n"
|
|
147
180
|
for agent_info in agents_run[-5:]: # Show last 5 agents
|
|
148
181
|
session_info += f" • {agent_info.get('agent', 'unknown')}: {agent_info.get('task', 'no description')[:50]}...\n"
|
|
149
182
|
if len(agents_run) > 5:
|
|
150
183
|
session_info += f" (and {len(agents_run) - 5} other agent interactions)\n"
|
|
151
|
-
|
|
184
|
+
|
|
152
185
|
session_info += "\nContinue from where you left off in this session."
|
|
153
|
-
|
|
186
|
+
|
|
154
187
|
return base_context + session_info
|
|
155
188
|
|
|
156
189
|
|
|
190
|
+
class RunCommand(BaseCommand):
|
|
191
|
+
"""Run command using shared utilities."""
|
|
192
|
+
|
|
193
|
+
def __init__(self):
|
|
194
|
+
super().__init__("run")
|
|
195
|
+
|
|
196
|
+
def validate_args(self, args) -> Optional[str]:
|
|
197
|
+
"""Validate command arguments."""
|
|
198
|
+
# Run command has minimal validation requirements
|
|
199
|
+
# Most validation is handled by the ClaudeRunner and related services
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
def run(self, args) -> CommandResult:
|
|
203
|
+
"""Execute the run command."""
|
|
204
|
+
try:
|
|
205
|
+
# Execute the main run logic
|
|
206
|
+
success = self._execute_run_session(args)
|
|
207
|
+
|
|
208
|
+
# Log memory stats at session completion
|
|
209
|
+
from ..startup_logging import log_memory_stats
|
|
210
|
+
|
|
211
|
+
log_memory_stats(self.logger, "Session End Memory")
|
|
212
|
+
|
|
213
|
+
if success:
|
|
214
|
+
return CommandResult.success_result(
|
|
215
|
+
"Claude session completed successfully"
|
|
216
|
+
)
|
|
217
|
+
return CommandResult.error_result("Claude session failed", exit_code=1)
|
|
218
|
+
|
|
219
|
+
except KeyboardInterrupt:
|
|
220
|
+
self.logger.info("Session interrupted by user")
|
|
221
|
+
return CommandResult.error_result(
|
|
222
|
+
"Session cancelled by user", exit_code=130
|
|
223
|
+
)
|
|
224
|
+
except Exception as e:
|
|
225
|
+
self.logger.error(f"Error running Claude session: {e}", exc_info=True)
|
|
226
|
+
return CommandResult.error_result(f"Error running Claude session: {e}")
|
|
227
|
+
|
|
228
|
+
def _execute_run_session(self, args) -> bool:
|
|
229
|
+
"""Execute the main run session logic."""
|
|
230
|
+
# For now, delegate to the legacy function to maintain compatibility
|
|
231
|
+
# TODO: Gradually migrate logic into the individual helper methods
|
|
232
|
+
try:
|
|
233
|
+
run_session_legacy(args)
|
|
234
|
+
return True
|
|
235
|
+
except Exception as e:
|
|
236
|
+
self.logger.error(f"Run session failed: {e}")
|
|
237
|
+
return False
|
|
238
|
+
|
|
239
|
+
def _execute_run_session_new(self, args) -> bool:
|
|
240
|
+
"""Execute the main run session logic using new pattern."""
|
|
241
|
+
try:
|
|
242
|
+
# Log session start
|
|
243
|
+
if args.logging != LogLevel.OFF.value:
|
|
244
|
+
self.logger.info("Starting Claude MPM session")
|
|
245
|
+
|
|
246
|
+
# Log MCP and monitor startup status
|
|
247
|
+
if args.logging != LogLevel.OFF.value:
|
|
248
|
+
monitor_mode = getattr(args, "monitor", False)
|
|
249
|
+
websocket_port = getattr(args, "websocket_port", 8765)
|
|
250
|
+
log_startup_status(monitor_mode, websocket_port)
|
|
251
|
+
|
|
252
|
+
# Perform startup checks
|
|
253
|
+
self._check_configuration_health()
|
|
254
|
+
self._check_claude_json_memory(args)
|
|
255
|
+
|
|
256
|
+
# Handle session management
|
|
257
|
+
session_manager, resume_session_id, resume_context = (
|
|
258
|
+
self._setup_session_management(args)
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Handle dependency checking
|
|
262
|
+
self._handle_dependency_checking(args)
|
|
263
|
+
|
|
264
|
+
# Setup monitoring if requested
|
|
265
|
+
monitor_mode, websocket_port = self._setup_monitoring(args)
|
|
266
|
+
|
|
267
|
+
# Configure Claude runner
|
|
268
|
+
runner = self._setup_claude_runner(args, monitor_mode, websocket_port)
|
|
269
|
+
|
|
270
|
+
# Create context and run session
|
|
271
|
+
context = self._create_session_context(
|
|
272
|
+
args, session_manager, resume_session_id, resume_context
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
# Execute the session
|
|
276
|
+
return self._execute_session(args, runner, context)
|
|
277
|
+
|
|
278
|
+
except Exception as e:
|
|
279
|
+
self.logger.error(f"Run session failed: {e}")
|
|
280
|
+
return False
|
|
281
|
+
|
|
282
|
+
def _check_configuration_health(self):
|
|
283
|
+
"""Check configuration health at startup."""
|
|
284
|
+
# Use new StartupCheckerService
|
|
285
|
+
from ...core.config import Config
|
|
286
|
+
|
|
287
|
+
config_service = Config()
|
|
288
|
+
checker = StartupCheckerService(config_service)
|
|
289
|
+
warnings = checker.check_configuration()
|
|
290
|
+
checker.display_warnings(warnings)
|
|
291
|
+
|
|
292
|
+
def _check_claude_json_memory(self, args):
|
|
293
|
+
"""Check .claude.json file size and warn about memory issues."""
|
|
294
|
+
# Use new StartupCheckerService
|
|
295
|
+
from ...core.config import Config
|
|
296
|
+
|
|
297
|
+
config_service = Config()
|
|
298
|
+
checker = StartupCheckerService(config_service)
|
|
299
|
+
resume_enabled = getattr(args, "mpm_resume", False)
|
|
300
|
+
warning = checker.check_memory(resume_enabled)
|
|
301
|
+
if warning:
|
|
302
|
+
checker.display_warnings([warning])
|
|
303
|
+
|
|
304
|
+
def _setup_session_management(self, args):
|
|
305
|
+
"""Setup session management and handle resumption."""
|
|
306
|
+
# Use the new SessionManager service from the CLI services layer
|
|
307
|
+
session_manager = SessionManager()
|
|
308
|
+
resume_session_id = None
|
|
309
|
+
resume_context = None
|
|
310
|
+
|
|
311
|
+
if hasattr(args, "mpm_resume") and args.mpm_resume:
|
|
312
|
+
if args.mpm_resume == "last":
|
|
313
|
+
# Resume the last interactive session
|
|
314
|
+
resume_session_id = session_manager.get_last_interactive_session()
|
|
315
|
+
if resume_session_id:
|
|
316
|
+
session_data = session_manager.get_session_info(resume_session_id)
|
|
317
|
+
if session_data:
|
|
318
|
+
resume_context = session_data.get("context", "default")
|
|
319
|
+
self.logger.info(
|
|
320
|
+
f"Resuming session {resume_session_id} (context: {resume_context})"
|
|
321
|
+
)
|
|
322
|
+
print(
|
|
323
|
+
f"🔄 Resuming session {resume_session_id[:8]}... (created: {session_data.get('created_at', 'unknown')})"
|
|
324
|
+
)
|
|
325
|
+
else:
|
|
326
|
+
self.logger.warning(f"Session {resume_session_id} not found")
|
|
327
|
+
else:
|
|
328
|
+
self.logger.info("No recent interactive sessions found")
|
|
329
|
+
print("[INFO]️ No recent interactive sessions found to resume")
|
|
330
|
+
else:
|
|
331
|
+
# Resume specific session by ID
|
|
332
|
+
resume_session_id = args.mpm_resume
|
|
333
|
+
session_data = session_manager.get_session_info(resume_session_id)
|
|
334
|
+
if session_data:
|
|
335
|
+
resume_context = session_data.get("context", "default")
|
|
336
|
+
self.logger.info(
|
|
337
|
+
f"Resuming session {resume_session_id} (context: {resume_context})"
|
|
338
|
+
)
|
|
339
|
+
print(
|
|
340
|
+
f"🔄 Resuming session {resume_session_id[:8]}... (context: {resume_context})"
|
|
341
|
+
)
|
|
342
|
+
else:
|
|
343
|
+
self.logger.error(f"Session {resume_session_id} not found")
|
|
344
|
+
print(f"❌ Session {resume_session_id} not found")
|
|
345
|
+
print("💡 Use 'claude-mpm sessions' to list available sessions")
|
|
346
|
+
raise RuntimeError(f"Session {resume_session_id} not found")
|
|
347
|
+
|
|
348
|
+
return session_manager, resume_session_id, resume_context
|
|
349
|
+
|
|
350
|
+
def _handle_dependency_checking(self, args):
|
|
351
|
+
"""Handle smart dependency checking."""
|
|
352
|
+
# Smart dependency checking - only when needed
|
|
353
|
+
if getattr(args, "check_dependencies", True): # Default to checking
|
|
354
|
+
try:
|
|
355
|
+
from ...utils.agent_dependency_loader import AgentDependencyLoader
|
|
356
|
+
from ...utils.dependency_cache import SmartDependencyChecker
|
|
357
|
+
from ...utils.environment_context import should_prompt_for_dependencies
|
|
358
|
+
|
|
359
|
+
# Initialize smart checker
|
|
360
|
+
smart_checker = SmartDependencyChecker()
|
|
361
|
+
loader = AgentDependencyLoader(auto_install=False)
|
|
362
|
+
|
|
363
|
+
# Check if agents have changed
|
|
364
|
+
_has_changed, deployment_hash = loader.has_agents_changed()
|
|
365
|
+
|
|
366
|
+
# Determine if we should check dependencies
|
|
367
|
+
should_check, check_reason = smart_checker.should_check_dependencies(
|
|
368
|
+
force_check=getattr(args, "force_check_dependencies", False),
|
|
369
|
+
deployment_hash=deployment_hash,
|
|
370
|
+
)
|
|
371
|
+
|
|
372
|
+
if should_check:
|
|
373
|
+
self.logger.info(f"Checking dependencies: {check_reason}")
|
|
374
|
+
|
|
375
|
+
# Check if we should prompt for dependencies
|
|
376
|
+
should_prompt = should_prompt_for_dependencies()
|
|
377
|
+
|
|
378
|
+
if should_prompt:
|
|
379
|
+
# Check dependencies and prompt for installation if needed
|
|
380
|
+
missing_deps = loader.check_dependencies()
|
|
381
|
+
if missing_deps:
|
|
382
|
+
self.logger.info(
|
|
383
|
+
f"Found {len(missing_deps)} missing dependencies"
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
# Prompt user for installation
|
|
387
|
+
print(
|
|
388
|
+
f"\n📦 Found {len(missing_deps)} missing dependencies:"
|
|
389
|
+
)
|
|
390
|
+
for dep in missing_deps[:5]: # Show first 5
|
|
391
|
+
print(f" • {dep}")
|
|
392
|
+
if len(missing_deps) > 5:
|
|
393
|
+
print(f" ... and {len(missing_deps) - 5} more")
|
|
394
|
+
|
|
395
|
+
response = (
|
|
396
|
+
input("\nInstall missing dependencies? (y/N): ")
|
|
397
|
+
.strip()
|
|
398
|
+
.lower()
|
|
399
|
+
)
|
|
400
|
+
if response in ["y", "yes"]:
|
|
401
|
+
loader.auto_install = True
|
|
402
|
+
loader.install_dependencies(missing_deps)
|
|
403
|
+
print("✅ Dependencies installed successfully")
|
|
404
|
+
else:
|
|
405
|
+
print("⚠️ Continuing without installing dependencies")
|
|
406
|
+
else:
|
|
407
|
+
# Just check without prompting
|
|
408
|
+
missing_deps = loader.check_dependencies()
|
|
409
|
+
if missing_deps:
|
|
410
|
+
self.logger.warning(
|
|
411
|
+
f"Found {len(missing_deps)} missing dependencies"
|
|
412
|
+
)
|
|
413
|
+
print(
|
|
414
|
+
f"⚠️ Found {len(missing_deps)} missing dependencies. Use --force-check-dependencies to install."
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
# Update cache
|
|
418
|
+
smart_checker.update_cache(deployment_hash)
|
|
419
|
+
else:
|
|
420
|
+
self.logger.debug(f"Skipping dependency check: {check_reason}")
|
|
421
|
+
|
|
422
|
+
except ImportError as e:
|
|
423
|
+
self.logger.warning(f"Dependency checking not available: {e}")
|
|
424
|
+
except Exception as e:
|
|
425
|
+
self.logger.warning(f"Dependency check failed: {e}")
|
|
426
|
+
|
|
427
|
+
def _setup_monitoring(self, args):
|
|
428
|
+
"""Setup monitoring configuration using UnifiedDashboardManager."""
|
|
429
|
+
monitor_mode = getattr(args, "monitor", False)
|
|
430
|
+
websocket_port = 8765 # Default port
|
|
431
|
+
|
|
432
|
+
if monitor_mode:
|
|
433
|
+
# Use UnifiedDashboardManager for server management
|
|
434
|
+
dashboard_manager = UnifiedDashboardManager(self.logger)
|
|
435
|
+
|
|
436
|
+
# Check dependencies
|
|
437
|
+
deps_ok, error_msg = dashboard_manager.ensure_dependencies()
|
|
438
|
+
if not deps_ok:
|
|
439
|
+
self.logger.warning(
|
|
440
|
+
f"Socket.IO dependencies not available: {error_msg}, disabling monitor mode"
|
|
441
|
+
)
|
|
442
|
+
monitor_mode = False
|
|
443
|
+
else:
|
|
444
|
+
# Find available port and start server
|
|
445
|
+
websocket_port = dashboard_manager.find_available_port(8765)
|
|
446
|
+
success, _server_info = dashboard_manager.start_server(
|
|
447
|
+
port=websocket_port
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
if not success:
|
|
451
|
+
self.logger.warning(
|
|
452
|
+
"Failed to start Socket.IO server, disabling monitor mode"
|
|
453
|
+
)
|
|
454
|
+
monitor_mode = False
|
|
455
|
+
else:
|
|
456
|
+
# Use UnifiedDashboardManager for browser opening only
|
|
457
|
+
dashboard_manager = UnifiedDashboardManager(self.logger)
|
|
458
|
+
monitor_url = dashboard_manager.get_dashboard_url(websocket_port)
|
|
459
|
+
|
|
460
|
+
# Try to open browser
|
|
461
|
+
browser_opened = dashboard_manager.open_browser(monitor_url)
|
|
462
|
+
args._browser_opened_by_cli = browser_opened
|
|
463
|
+
|
|
464
|
+
if not browser_opened:
|
|
465
|
+
print(f"💡 Monitor interface available at: {monitor_url}")
|
|
466
|
+
|
|
467
|
+
return monitor_mode, websocket_port
|
|
468
|
+
|
|
469
|
+
def _setup_claude_runner(self, args, monitor_mode: bool, websocket_port: int):
|
|
470
|
+
"""Setup and configure the Claude runner."""
|
|
471
|
+
try:
|
|
472
|
+
from ...core.claude_runner import ClaudeRunner
|
|
473
|
+
except ImportError:
|
|
474
|
+
from claude_mpm.core.claude_runner import ClaudeRunner
|
|
475
|
+
|
|
476
|
+
# Configure tickets
|
|
477
|
+
enable_tickets = not getattr(args, "no_tickets", False)
|
|
478
|
+
|
|
479
|
+
# Configure launch method
|
|
480
|
+
launch_method = "exec" # Default
|
|
481
|
+
if getattr(args, "subprocess", False):
|
|
482
|
+
launch_method = "subprocess"
|
|
483
|
+
|
|
484
|
+
# Configure WebSocket
|
|
485
|
+
enable_websocket = monitor_mode
|
|
486
|
+
|
|
487
|
+
# Build Claude arguments
|
|
488
|
+
claude_args = []
|
|
489
|
+
if hasattr(args, "claude_args") and args.claude_args:
|
|
490
|
+
claude_args.extend(args.claude_args)
|
|
491
|
+
|
|
492
|
+
# Create runner
|
|
493
|
+
runner = ClaudeRunner(
|
|
494
|
+
enable_tickets=enable_tickets,
|
|
495
|
+
log_level=args.logging,
|
|
496
|
+
claude_args=claude_args,
|
|
497
|
+
launch_method=launch_method,
|
|
498
|
+
enable_websocket=enable_websocket,
|
|
499
|
+
websocket_port=websocket_port,
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
# Set browser opening flag for monitor mode
|
|
503
|
+
if monitor_mode:
|
|
504
|
+
runner._should_open_monitor_browser = True
|
|
505
|
+
runner._browser_opened_by_cli = getattr(
|
|
506
|
+
args, "_browser_opened_by_cli", False
|
|
507
|
+
)
|
|
508
|
+
|
|
509
|
+
return runner
|
|
510
|
+
|
|
511
|
+
def _create_session_context(
|
|
512
|
+
self, args, session_manager, resume_session_id, resume_context
|
|
513
|
+
):
|
|
514
|
+
"""Create session context."""
|
|
515
|
+
try:
|
|
516
|
+
from ...core.claude_runner import create_simple_context
|
|
517
|
+
except ImportError:
|
|
518
|
+
from claude_mpm.core.claude_runner import create_simple_context
|
|
519
|
+
|
|
520
|
+
if resume_session_id and resume_context:
|
|
521
|
+
# For resumed sessions, create enhanced context with session information
|
|
522
|
+
context = create_session_context(resume_session_id, session_manager)
|
|
523
|
+
# Update session usage
|
|
524
|
+
session = session_manager.load_session(resume_session_id)
|
|
525
|
+
if session:
|
|
526
|
+
session.last_used = datetime.now(timezone.utc).isoformat()
|
|
527
|
+
session.use_count += 1
|
|
528
|
+
session_manager.save_session(session)
|
|
529
|
+
else:
|
|
530
|
+
# Create a new session for tracking
|
|
531
|
+
new_session = session_manager.create_session("default")
|
|
532
|
+
context = create_simple_context()
|
|
533
|
+
self.logger.info(f"Created new session {new_session.id}")
|
|
534
|
+
|
|
535
|
+
return context
|
|
536
|
+
|
|
537
|
+
def _execute_session(self, args, runner, context) -> bool:
|
|
538
|
+
"""Execute the Claude session."""
|
|
539
|
+
try:
|
|
540
|
+
# Run session based on mode
|
|
541
|
+
non_interactive = getattr(args, "non_interactive", False)
|
|
542
|
+
input_arg = getattr(args, "input", None)
|
|
543
|
+
|
|
544
|
+
if non_interactive or input_arg:
|
|
545
|
+
# Non-interactive mode
|
|
546
|
+
user_input = get_user_input(input_arg, self.logger)
|
|
547
|
+
success = runner.run_oneshot(user_input, context)
|
|
548
|
+
if not success:
|
|
549
|
+
self.logger.error("Session failed")
|
|
550
|
+
return False
|
|
551
|
+
# Interactive mode
|
|
552
|
+
elif getattr(args, "intercept_commands", False):
|
|
553
|
+
wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
|
|
554
|
+
if wrapper_path.exists():
|
|
555
|
+
print("Starting interactive session with command interception...")
|
|
556
|
+
subprocess.run([sys.executable, str(wrapper_path)], check=False)
|
|
557
|
+
else:
|
|
558
|
+
self.logger.warning(
|
|
559
|
+
"Interactive wrapper not found, falling back to normal mode"
|
|
560
|
+
)
|
|
561
|
+
runner.run_interactive(context)
|
|
562
|
+
else:
|
|
563
|
+
runner.run_interactive(context)
|
|
564
|
+
|
|
565
|
+
return True
|
|
566
|
+
|
|
567
|
+
except Exception as e:
|
|
568
|
+
self.logger.error(f"Session execution failed: {e}")
|
|
569
|
+
return False
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
def _handle_reload_agents(logger):
|
|
573
|
+
"""
|
|
574
|
+
Handle the --reload-agents flag by deleting all local claude-mpm system agents.
|
|
575
|
+
|
|
576
|
+
This forces a fresh rebuild of system agents on the next deployment,
|
|
577
|
+
while preserving user-created agents.
|
|
578
|
+
|
|
579
|
+
Args:
|
|
580
|
+
logger: Logger instance for output
|
|
581
|
+
"""
|
|
582
|
+
try:
|
|
583
|
+
logger.info("Reloading system agents - cleaning existing deployments...")
|
|
584
|
+
|
|
585
|
+
# Import the cleanup service
|
|
586
|
+
from ...services.agents.deployment.agent_deployment import (
|
|
587
|
+
AgentDeploymentService,
|
|
588
|
+
)
|
|
589
|
+
from ...services.cli.agent_cleanup_service import AgentCleanupService
|
|
590
|
+
|
|
591
|
+
# Create services
|
|
592
|
+
deployment_service = AgentDeploymentService()
|
|
593
|
+
cleanup_service = AgentCleanupService(deployment_service)
|
|
594
|
+
|
|
595
|
+
# Determine the agents directory
|
|
596
|
+
agents_dir = None # Will auto-detect project or user directory
|
|
597
|
+
|
|
598
|
+
# Clean deployed agents (preserves user agents)
|
|
599
|
+
result = cleanup_service.clean_deployed_agents(agents_dir)
|
|
600
|
+
|
|
601
|
+
# Check if cleanup was successful based on the result structure
|
|
602
|
+
# The service returns a dict with 'removed', 'preserved', and possibly 'errors' keys
|
|
603
|
+
# If it has 'success' key, use it; otherwise infer from the result
|
|
604
|
+
success = (
|
|
605
|
+
result.get("success", True)
|
|
606
|
+
if "success" in result
|
|
607
|
+
else not result.get("errors")
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
if success:
|
|
611
|
+
removed_count = result.get("cleaned_count", len(result.get("removed", [])))
|
|
612
|
+
removed_agents = result.get("removed", [])
|
|
613
|
+
preserved_agents = result.get("preserved", [])
|
|
614
|
+
|
|
615
|
+
if removed_count > 0:
|
|
616
|
+
logger.info(f"✅ Successfully removed {removed_count} system agents")
|
|
617
|
+
if removed_agents:
|
|
618
|
+
logger.debug(f"Removed agents: {', '.join(removed_agents)}")
|
|
619
|
+
print(f"🔄 Cleaned {removed_count} claude-mpm system agents")
|
|
620
|
+
else:
|
|
621
|
+
logger.info("No system agents found to clean")
|
|
622
|
+
print("[INFO]️ No system agents found - already clean")
|
|
623
|
+
|
|
624
|
+
if preserved_agents:
|
|
625
|
+
logger.info(f"Preserved {len(preserved_agents)} user-created agents")
|
|
626
|
+
print(f"✅ Preserved {len(preserved_agents)} user-created agents")
|
|
627
|
+
|
|
628
|
+
print("🚀 System agents will be rebuilt on next use")
|
|
629
|
+
else:
|
|
630
|
+
error = result.get("error", "Cleanup failed")
|
|
631
|
+
if result.get("errors"):
|
|
632
|
+
error = f"Cleanup errors: {', '.join(result['errors'])}"
|
|
633
|
+
logger.error(f"Failed to clean system agents: {error}")
|
|
634
|
+
print(f"❌ Error cleaning agents: {error}")
|
|
635
|
+
|
|
636
|
+
except Exception as e:
|
|
637
|
+
logger.error(f"Error handling --reload-agents: {e}", exc_info=True)
|
|
638
|
+
print(f"❌ Failed to reload agents: {e}")
|
|
639
|
+
# Don't fail the entire session, just log the error
|
|
640
|
+
print("⚠️ Continuing with existing agents...")
|
|
641
|
+
|
|
642
|
+
|
|
157
643
|
def run_session(args):
|
|
158
644
|
"""
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
645
|
+
Main entry point for run command.
|
|
646
|
+
|
|
647
|
+
This function maintains backward compatibility while using the new BaseCommand pattern.
|
|
648
|
+
"""
|
|
649
|
+
command = RunCommand()
|
|
650
|
+
result = command.execute(args)
|
|
651
|
+
|
|
652
|
+
# For run command, we don't typically need structured output
|
|
653
|
+
# but we should respect the exit code
|
|
654
|
+
return result.exit_code
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def run_session_legacy(args):
|
|
658
|
+
"""
|
|
659
|
+
Legacy run session implementation.
|
|
660
|
+
|
|
661
|
+
WHY: This contains the original run_session logic, preserved during migration
|
|
662
|
+
to BaseCommand pattern. Will be gradually refactored into the RunCommand class.
|
|
663
|
+
|
|
164
664
|
DESIGN DECISION: We use ClaudeRunner to handle the complexity of
|
|
165
665
|
subprocess management and hook integration, keeping this function focused
|
|
166
666
|
on high-level orchestration.
|
|
167
|
-
|
|
667
|
+
|
|
168
668
|
Args:
|
|
169
669
|
args: Parsed command line arguments
|
|
170
670
|
"""
|
|
671
|
+
# Only setup startup logging if user wants logging
|
|
672
|
+
if args.logging != LogLevel.OFF.value:
|
|
673
|
+
# Set up startup logging to file early in the process
|
|
674
|
+
setup_startup_logging(Path.cwd())
|
|
675
|
+
|
|
171
676
|
logger = get_logger("cli")
|
|
172
677
|
if args.logging != LogLevel.OFF.value:
|
|
173
678
|
logger.info("Starting Claude MPM session")
|
|
174
|
-
|
|
679
|
+
# Log file already announced in startup_logging.py when created
|
|
680
|
+
|
|
681
|
+
# Clean up old startup logs (using configured retention count)
|
|
682
|
+
if args.logging != LogLevel.OFF.value:
|
|
683
|
+
try:
|
|
684
|
+
deleted_count = cleanup_old_startup_logs(Path.cwd())
|
|
685
|
+
if deleted_count > 0:
|
|
686
|
+
logger.debug(f"Cleaned up {deleted_count} old startup log files")
|
|
687
|
+
except Exception as e:
|
|
688
|
+
logger.debug(f"Failed to clean up old logs: {e}")
|
|
689
|
+
|
|
690
|
+
# Log MCP and monitor startup status
|
|
691
|
+
if args.logging != LogLevel.OFF.value:
|
|
692
|
+
monitor_mode = getattr(args, "monitor", False)
|
|
693
|
+
websocket_port = getattr(args, "websocket_port", 8765)
|
|
694
|
+
log_startup_status(monitor_mode, websocket_port)
|
|
695
|
+
|
|
696
|
+
# Perform startup configuration check
|
|
697
|
+
_check_configuration_health(logger)
|
|
698
|
+
|
|
699
|
+
# Check for memory usage issues with .claude.json
|
|
700
|
+
_check_claude_json_memory(args, logger)
|
|
701
|
+
|
|
702
|
+
# Handle --reload-agents flag if specified
|
|
703
|
+
if getattr(args, "reload_agents", False):
|
|
704
|
+
_handle_reload_agents(logger)
|
|
705
|
+
|
|
706
|
+
# Trigger vector search indexing
|
|
707
|
+
try:
|
|
708
|
+
from ...cli.startup_logging import start_vector_search_indexing
|
|
709
|
+
|
|
710
|
+
start_vector_search_indexing()
|
|
711
|
+
except Exception as e:
|
|
712
|
+
logger.debug(f"Failed to start vector search indexing: {e}")
|
|
713
|
+
|
|
175
714
|
try:
|
|
176
715
|
from ...core.claude_runner import ClaudeRunner, create_simple_context
|
|
177
|
-
from ...core.session_manager import SessionManager
|
|
178
716
|
except ImportError:
|
|
179
717
|
from claude_mpm.core.claude_runner import ClaudeRunner, create_simple_context
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
# Handle session resumption
|
|
718
|
+
|
|
719
|
+
# Handle session resumption using the new SessionManager service
|
|
183
720
|
session_manager = SessionManager()
|
|
184
721
|
resume_session_id = None
|
|
185
722
|
resume_context = None
|
|
186
|
-
|
|
187
|
-
if hasattr(args,
|
|
188
|
-
if args.
|
|
723
|
+
|
|
724
|
+
if hasattr(args, "mpm_resume") and args.mpm_resume:
|
|
725
|
+
if args.mpm_resume == "last":
|
|
189
726
|
# Resume the last interactive session
|
|
190
727
|
resume_session_id = session_manager.get_last_interactive_session()
|
|
191
728
|
if resume_session_id:
|
|
192
|
-
session_data = session_manager.
|
|
729
|
+
session_data = session_manager.get_session_info(resume_session_id)
|
|
193
730
|
if session_data:
|
|
194
731
|
resume_context = session_data.get("context", "default")
|
|
195
|
-
logger.info(
|
|
196
|
-
|
|
732
|
+
logger.info(
|
|
733
|
+
f"Resuming session {resume_session_id} (context: {resume_context})"
|
|
734
|
+
)
|
|
735
|
+
print(
|
|
736
|
+
f"🔄 Resuming session {resume_session_id[:8]}... (created: {session_data.get('created_at', 'unknown')})"
|
|
737
|
+
)
|
|
197
738
|
else:
|
|
198
739
|
logger.warning(f"Session {resume_session_id} not found")
|
|
199
740
|
else:
|
|
200
741
|
logger.info("No recent interactive sessions found")
|
|
201
|
-
print("
|
|
742
|
+
print("[INFO]️ No recent interactive sessions found to resume")
|
|
202
743
|
else:
|
|
203
744
|
# Resume specific session by ID
|
|
204
|
-
resume_session_id = args.
|
|
205
|
-
session_data = session_manager.
|
|
745
|
+
resume_session_id = args.mpm_resume
|
|
746
|
+
session_data = session_manager.get_session_info(resume_session_id)
|
|
206
747
|
if session_data:
|
|
207
748
|
resume_context = session_data.get("context", "default")
|
|
208
|
-
logger.info(
|
|
209
|
-
|
|
749
|
+
logger.info(
|
|
750
|
+
f"Resuming session {resume_session_id} (context: {resume_context})"
|
|
751
|
+
)
|
|
752
|
+
print(
|
|
753
|
+
f"🔄 Resuming session {resume_session_id[:8]}... (context: {resume_context})"
|
|
754
|
+
)
|
|
210
755
|
else:
|
|
211
756
|
logger.error(f"Session {resume_session_id} not found")
|
|
212
757
|
print(f"❌ Session {resume_session_id} not found")
|
|
213
758
|
print("💡 Use 'claude-mpm sessions' to list available sessions")
|
|
214
759
|
return
|
|
215
|
-
|
|
760
|
+
|
|
761
|
+
# Deploy MPM slash commands to user's Claude configuration
|
|
762
|
+
try:
|
|
763
|
+
from ...services.command_deployment_service import deploy_commands_on_startup
|
|
764
|
+
|
|
765
|
+
deploy_commands_on_startup(force=False)
|
|
766
|
+
except Exception as e:
|
|
767
|
+
logger.debug(f"Failed to deploy MPM commands (non-critical): {e}")
|
|
768
|
+
|
|
216
769
|
# Skip native agents if disabled
|
|
217
|
-
if getattr(args,
|
|
770
|
+
if getattr(args, "no_native_agents", False):
|
|
218
771
|
print("Native agents disabled")
|
|
219
772
|
else:
|
|
220
|
-
#
|
|
221
|
-
list_agent_versions_at_startup()
|
|
222
|
-
|
|
773
|
+
# Agent versions removed from startup display - use /mpm-agents to view
|
|
774
|
+
# list_agent_versions_at_startup()
|
|
775
|
+
pass
|
|
776
|
+
|
|
777
|
+
# Smart dependency checking - only when needed
|
|
778
|
+
if getattr(args, "check_dependencies", True): # Default to checking
|
|
779
|
+
try:
|
|
780
|
+
from ...utils.agent_dependency_loader import AgentDependencyLoader
|
|
781
|
+
from ...utils.dependency_cache import SmartDependencyChecker
|
|
782
|
+
from ...utils.environment_context import should_prompt_for_dependencies
|
|
783
|
+
|
|
784
|
+
# Initialize smart checker
|
|
785
|
+
smart_checker = SmartDependencyChecker()
|
|
786
|
+
loader = AgentDependencyLoader(auto_install=False)
|
|
787
|
+
|
|
788
|
+
# Check if agents have changed
|
|
789
|
+
_has_changed, deployment_hash = loader.has_agents_changed()
|
|
790
|
+
|
|
791
|
+
# Determine if we should check dependencies
|
|
792
|
+
should_check, check_reason = smart_checker.should_check_dependencies(
|
|
793
|
+
force_check=getattr(args, "force_check_dependencies", False),
|
|
794
|
+
deployment_hash=deployment_hash,
|
|
795
|
+
)
|
|
796
|
+
|
|
797
|
+
if should_check:
|
|
798
|
+
# Check if we're in an environment where prompting makes sense
|
|
799
|
+
can_prompt, prompt_reason = should_prompt_for_dependencies(
|
|
800
|
+
force_prompt=getattr(args, "force_prompt", False),
|
|
801
|
+
force_skip=getattr(args, "no_prompt", False),
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
logger.debug(f"Dependency check needed: {check_reason}")
|
|
805
|
+
logger.debug(f"Interactive prompting: {can_prompt} ({prompt_reason})")
|
|
806
|
+
|
|
807
|
+
# Get or check dependencies
|
|
808
|
+
results, was_cached = smart_checker.get_or_check_dependencies(
|
|
809
|
+
loader=loader,
|
|
810
|
+
force_check=getattr(args, "force_check_dependencies", False),
|
|
811
|
+
)
|
|
812
|
+
|
|
813
|
+
# Show summary if there are missing dependencies
|
|
814
|
+
if results["summary"]["missing_python"]:
|
|
815
|
+
missing_count = len(results["summary"]["missing_python"])
|
|
816
|
+
print(f"⚠️ {missing_count} agent dependencies missing")
|
|
817
|
+
|
|
818
|
+
if can_prompt and missing_count > 0:
|
|
819
|
+
# Interactive prompt for installation
|
|
820
|
+
print("\n📦 Missing dependencies detected:")
|
|
821
|
+
for dep in results["summary"]["missing_python"][:5]:
|
|
822
|
+
print(f" - {dep}")
|
|
823
|
+
if missing_count > 5:
|
|
824
|
+
print(f" ... and {missing_count - 5} more")
|
|
825
|
+
|
|
826
|
+
print("\nWould you like to install them now?")
|
|
827
|
+
print(" [y] Yes, install missing dependencies")
|
|
828
|
+
print(" [n] No, continue without installing")
|
|
829
|
+
print(" [q] Quit")
|
|
830
|
+
|
|
831
|
+
sys.stdout.flush() # Ensure prompt is displayed before input
|
|
832
|
+
|
|
833
|
+
# Check if we're in a TTY environment for proper input handling
|
|
834
|
+
if not sys.stdin.isatty():
|
|
835
|
+
# In non-TTY environment (like pipes), use readline
|
|
836
|
+
print("\nChoice [y/n/q]: ", end="", flush=True)
|
|
837
|
+
try:
|
|
838
|
+
response = sys.stdin.readline().strip().lower()
|
|
839
|
+
# Handle various line endings and control characters
|
|
840
|
+
response = (
|
|
841
|
+
response.replace("\r", "").replace("\n", "").strip()
|
|
842
|
+
)
|
|
843
|
+
except (EOFError, KeyboardInterrupt):
|
|
844
|
+
response = "q"
|
|
845
|
+
else:
|
|
846
|
+
# In TTY environment, use normal input()
|
|
847
|
+
try:
|
|
848
|
+
response = input("\nChoice [y/n/q]: ").strip().lower()
|
|
849
|
+
except (EOFError, KeyboardInterrupt):
|
|
850
|
+
response = "q"
|
|
851
|
+
|
|
852
|
+
try:
|
|
853
|
+
if response == "y":
|
|
854
|
+
print("\n🔧 Installing missing dependencies...")
|
|
855
|
+
loader.auto_install = True
|
|
856
|
+
(
|
|
857
|
+
success,
|
|
858
|
+
error,
|
|
859
|
+
) = loader.install_missing_dependencies(
|
|
860
|
+
results["summary"]["missing_python"]
|
|
861
|
+
)
|
|
862
|
+
if success:
|
|
863
|
+
print("✅ Dependencies installed successfully")
|
|
864
|
+
# Invalidate cache after installation
|
|
865
|
+
smart_checker.cache.invalidate(deployment_hash)
|
|
866
|
+
else:
|
|
867
|
+
print(f"❌ Installation failed: {error}")
|
|
868
|
+
elif response == "q":
|
|
869
|
+
print("👋 Exiting...")
|
|
870
|
+
return
|
|
871
|
+
else:
|
|
872
|
+
print("⏩ Continuing without installing dependencies")
|
|
873
|
+
except (EOFError, KeyboardInterrupt):
|
|
874
|
+
print("\n⏩ Continuing without installing dependencies")
|
|
875
|
+
else:
|
|
876
|
+
# Non-interactive environment or prompting disabled
|
|
877
|
+
print(
|
|
878
|
+
" Run 'pip install \"claude-mpm[agents]\"' to install all agent dependencies"
|
|
879
|
+
)
|
|
880
|
+
if not can_prompt:
|
|
881
|
+
logger.debug(
|
|
882
|
+
f"Not prompting for installation: {prompt_reason}"
|
|
883
|
+
)
|
|
884
|
+
elif was_cached:
|
|
885
|
+
logger.debug("Dependencies satisfied (cached result)")
|
|
886
|
+
else:
|
|
887
|
+
logger.debug("All dependencies satisfied")
|
|
888
|
+
else:
|
|
889
|
+
logger.debug(f"Skipping dependency check: {check_reason}")
|
|
890
|
+
|
|
891
|
+
except Exception as e:
|
|
892
|
+
if args.logging != LogLevel.OFF.value:
|
|
893
|
+
logger.debug(f"Could not check agent dependencies: {e}")
|
|
894
|
+
# Continue anyway - don't block execution
|
|
895
|
+
|
|
223
896
|
# Create simple runner
|
|
224
897
|
enable_tickets = not args.no_tickets
|
|
225
|
-
raw_claude_args = getattr(args,
|
|
898
|
+
raw_claude_args = getattr(args, "claude_args", []) or []
|
|
899
|
+
|
|
900
|
+
# Add --resume to claude_args if the flag is set
|
|
901
|
+
resume_flag_present = getattr(args, "resume", False)
|
|
902
|
+
if resume_flag_present:
|
|
903
|
+
logger.info("📌 --resume flag detected in args")
|
|
904
|
+
if "--resume" not in raw_claude_args:
|
|
905
|
+
raw_claude_args = ["--resume", *raw_claude_args]
|
|
906
|
+
logger.info("✅ Added --resume to claude_args")
|
|
907
|
+
else:
|
|
908
|
+
logger.info("[INFO]️ --resume already in claude_args")
|
|
909
|
+
|
|
226
910
|
# Filter out claude-mpm specific flags before passing to Claude CLI
|
|
911
|
+
logger.debug(f"Pre-filter claude_args: {raw_claude_args}")
|
|
227
912
|
claude_args = filter_claude_mpm_args(raw_claude_args)
|
|
228
|
-
monitor_mode = getattr(args,
|
|
229
|
-
|
|
230
|
-
#
|
|
913
|
+
monitor_mode = getattr(args, "monitor", False)
|
|
914
|
+
|
|
915
|
+
# Enhanced debug logging for argument filtering
|
|
231
916
|
if raw_claude_args != claude_args:
|
|
232
|
-
|
|
233
|
-
logger.debug(f"
|
|
234
|
-
|
|
917
|
+
filtered_out = list(set(raw_claude_args) - set(claude_args))
|
|
918
|
+
logger.debug(f"Filtered out MPM-specific args: {filtered_out}")
|
|
919
|
+
|
|
920
|
+
logger.info(f"Final claude_args being passed: {claude_args}")
|
|
921
|
+
|
|
922
|
+
# Explicit verification of --resume flag
|
|
923
|
+
if resume_flag_present:
|
|
924
|
+
if "--resume" in claude_args:
|
|
925
|
+
logger.info("✅ CONFIRMED: --resume flag will be passed to Claude CLI")
|
|
926
|
+
else:
|
|
927
|
+
logger.error("❌ WARNING: --resume flag was filtered out! This is a bug!")
|
|
928
|
+
logger.error(f" Original args: {raw_claude_args}")
|
|
929
|
+
logger.error(f" Filtered args: {claude_args}")
|
|
930
|
+
|
|
235
931
|
# Use the specified launch method (default: exec)
|
|
236
|
-
launch_method = getattr(args,
|
|
237
|
-
|
|
238
|
-
enable_websocket = getattr(args,
|
|
239
|
-
websocket_port = getattr(args,
|
|
240
|
-
|
|
932
|
+
launch_method = getattr(args, "launch_method", "exec")
|
|
933
|
+
|
|
934
|
+
enable_websocket = getattr(args, "monitor", False) or monitor_mode
|
|
935
|
+
websocket_port = getattr(args, "websocket_port", 8765)
|
|
936
|
+
|
|
241
937
|
# Display Socket.IO server info if enabled
|
|
242
938
|
if enable_websocket:
|
|
243
|
-
#
|
|
939
|
+
# Use UnifiedDashboardManager for server management
|
|
940
|
+
dashboard_manager = UnifiedDashboardManager(logger)
|
|
941
|
+
|
|
942
|
+
# Check dependencies
|
|
244
943
|
print("🔧 Checking Socket.IO dependencies...")
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
if not
|
|
944
|
+
deps_ok, error_msg = dashboard_manager.ensure_dependencies()
|
|
945
|
+
|
|
946
|
+
if not deps_ok:
|
|
248
947
|
print(f"❌ Failed to install Socket.IO dependencies: {error_msg}")
|
|
249
|
-
print(
|
|
948
|
+
print(
|
|
949
|
+
" Please install manually: pip install python-socketio aiohttp python-engineio"
|
|
950
|
+
)
|
|
250
951
|
print(" Or install with extras: pip install claude-mpm[monitor]")
|
|
251
952
|
# Continue anyway - some functionality might still work
|
|
252
953
|
else:
|
|
253
954
|
print("✓ Socket.IO dependencies ready")
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
import socketio
|
|
257
|
-
print(f"✓ Socket.IO server enabled at http://localhost:{websocket_port}")
|
|
258
|
-
if launch_method == "exec":
|
|
259
|
-
print(" Note: Socket.IO monitoring using exec mode with Claude Code hooks")
|
|
260
|
-
|
|
261
|
-
# Launch Socket.IO dashboard if in monitor mode
|
|
955
|
+
|
|
956
|
+
# Find available port and start server if in monitor mode
|
|
262
957
|
if monitor_mode:
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
958
|
+
websocket_port = dashboard_manager.find_available_port(websocket_port)
|
|
959
|
+
success, server_info = dashboard_manager.start_server(
|
|
960
|
+
port=websocket_port
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
if success:
|
|
964
|
+
print(f"✓ Socket.IO server enabled at {server_info.url}")
|
|
965
|
+
if launch_method == "exec":
|
|
966
|
+
print(
|
|
967
|
+
" Note: Socket.IO monitoring using exec mode with Claude Code hooks"
|
|
968
|
+
)
|
|
969
|
+
|
|
970
|
+
# Use UnifiedDashboardManager for browser opening
|
|
971
|
+
dashboard_manager = UnifiedDashboardManager(logger)
|
|
972
|
+
monitor_url = dashboard_manager.get_dashboard_url(websocket_port)
|
|
973
|
+
browser_opened = dashboard_manager.open_browser(monitor_url)
|
|
974
|
+
args._browser_opened_by_cli = browser_opened
|
|
975
|
+
|
|
976
|
+
if not browser_opened:
|
|
977
|
+
print(f"💡 Monitor interface available at: {monitor_url}")
|
|
978
|
+
else:
|
|
979
|
+
print("⚠️ Failed to launch Socket.IO monitor")
|
|
980
|
+
print("Dashboard is not running. To enable monitoring:")
|
|
981
|
+
print(" 1. Use the --monitor flag: claude-mpm run --monitor")
|
|
982
|
+
print(
|
|
983
|
+
" 2. Or start dashboard separately: claude-mpm dashboard start"
|
|
984
|
+
)
|
|
985
|
+
print(
|
|
986
|
+
f" 3. Dashboard will be available at: http://localhost:{websocket_port}"
|
|
987
|
+
)
|
|
988
|
+
args._browser_opened_by_cli = False
|
|
989
|
+
else:
|
|
990
|
+
print(f"✓ Socket.IO ready (port: {websocket_port})")
|
|
991
|
+
|
|
275
992
|
runner = ClaudeRunner(
|
|
276
993
|
enable_tickets=enable_tickets,
|
|
277
994
|
log_level=args.logging,
|
|
278
995
|
claude_args=claude_args,
|
|
279
996
|
launch_method=launch_method,
|
|
280
997
|
enable_websocket=enable_websocket,
|
|
281
|
-
websocket_port=websocket_port
|
|
998
|
+
websocket_port=websocket_port,
|
|
282
999
|
)
|
|
283
|
-
|
|
1000
|
+
|
|
1001
|
+
# Agent deployment is handled by ClaudeRunner.setup_agents() and
|
|
1002
|
+
# ClaudeRunner.deploy_project_agents_to_claude() which are called
|
|
1003
|
+
# in both run_interactive() and run_oneshot() methods.
|
|
1004
|
+
# No need for redundant deployment here.
|
|
1005
|
+
|
|
284
1006
|
# Set browser opening flag for monitor mode
|
|
285
1007
|
if monitor_mode:
|
|
286
1008
|
runner._should_open_monitor_browser = True
|
|
287
1009
|
# Pass information about whether we already opened the browser in run.py
|
|
288
|
-
runner._browser_opened_by_cli = getattr(args,
|
|
289
|
-
|
|
1010
|
+
runner._browser_opened_by_cli = getattr(args, "_browser_opened_by_cli", False)
|
|
1011
|
+
|
|
290
1012
|
# Create context - use resumed session context if available
|
|
291
1013
|
if resume_session_id and resume_context:
|
|
292
1014
|
# For resumed sessions, create enhanced context with session information
|
|
293
1015
|
context = create_session_context(resume_session_id, session_manager)
|
|
294
1016
|
# Update session usage
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
1017
|
+
session = session_manager.load_session(resume_session_id)
|
|
1018
|
+
if session:
|
|
1019
|
+
session.last_used = datetime.now(timezone.utc).isoformat()
|
|
1020
|
+
session.use_count += 1
|
|
1021
|
+
session_manager.save_session(session)
|
|
298
1022
|
else:
|
|
299
1023
|
# Create a new session for tracking
|
|
300
|
-
|
|
1024
|
+
new_session = session_manager.create_session("default")
|
|
301
1025
|
context = create_simple_context()
|
|
302
|
-
logger.info(f"Created new session {
|
|
303
|
-
|
|
1026
|
+
logger.info(f"Created new session {new_session.id}")
|
|
1027
|
+
|
|
304
1028
|
# For monitor mode, we handled everything in launch_socketio_monitor
|
|
305
1029
|
# No need for ClaudeRunner browser delegation
|
|
306
1030
|
if monitor_mode:
|
|
307
1031
|
# Clear any browser opening flags since we handled it completely
|
|
308
1032
|
runner._should_open_monitor_browser = False
|
|
309
1033
|
runner._browser_opened_by_cli = True # Prevent duplicate opening
|
|
310
|
-
|
|
1034
|
+
|
|
311
1035
|
# Run session based on mode
|
|
312
1036
|
if args.non_interactive or args.input:
|
|
313
1037
|
# Non-interactive mode
|
|
@@ -315,373 +1039,71 @@ def run_session(args):
|
|
|
315
1039
|
success = runner.run_oneshot(user_input, context)
|
|
316
1040
|
if not success:
|
|
317
1041
|
logger.error("Session failed")
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
|
|
325
|
-
if wrapper_path.exists():
|
|
326
|
-
print("Starting interactive session with command interception...")
|
|
327
|
-
subprocess.run([sys.executable, str(wrapper_path)])
|
|
328
|
-
else:
|
|
329
|
-
logger.warning("Interactive wrapper not found, falling back to normal mode")
|
|
330
|
-
runner.run_interactive(context)
|
|
1042
|
+
# Interactive mode
|
|
1043
|
+
elif getattr(args, "intercept_commands", False):
|
|
1044
|
+
wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
|
|
1045
|
+
if wrapper_path.exists():
|
|
1046
|
+
print("Starting interactive session with command interception...")
|
|
1047
|
+
subprocess.run([sys.executable, str(wrapper_path)], check=False)
|
|
331
1048
|
else:
|
|
1049
|
+
logger.warning("Interactive wrapper not found, falling back to normal mode")
|
|
332
1050
|
runner.run_interactive(context)
|
|
1051
|
+
else:
|
|
1052
|
+
runner.run_interactive(context)
|
|
333
1053
|
|
|
334
1054
|
|
|
1055
|
+
# Legacy helper functions - now delegating to UnifiedDashboardManager
|
|
335
1056
|
def launch_socketio_monitor(port, logger):
|
|
336
|
-
"""
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
Args:
|
|
348
|
-
port: Port number for the Socket.IO server
|
|
349
|
-
logger: Logger instance for output
|
|
350
|
-
|
|
351
|
-
Returns:
|
|
352
|
-
tuple: (success: bool, browser_opened: bool) - success status and whether browser was opened
|
|
353
|
-
"""
|
|
354
|
-
try:
|
|
355
|
-
# Verify Socket.IO dependencies are available
|
|
356
|
-
try:
|
|
357
|
-
import socketio
|
|
358
|
-
import aiohttp
|
|
359
|
-
import engineio
|
|
360
|
-
logger.debug("Socket.IO dependencies verified")
|
|
361
|
-
except ImportError as e:
|
|
362
|
-
logger.error(f"Socket.IO dependencies not available: {e}")
|
|
363
|
-
print(f"❌ Socket.IO dependencies missing: {e}")
|
|
364
|
-
print(" This is unexpected - dependency installation may have failed.")
|
|
365
|
-
return False, False
|
|
366
|
-
|
|
367
|
-
print(f"🚀 Setting up Socket.IO monitor on port {port}...")
|
|
368
|
-
logger.info(f"Launching Socket.IO monitor on port {port}")
|
|
369
|
-
|
|
370
|
-
socketio_port = port
|
|
371
|
-
|
|
372
|
-
# Use HTTP URL to access dashboard from Socket.IO server
|
|
373
|
-
dashboard_url = f'http://localhost:{socketio_port}'
|
|
374
|
-
|
|
375
|
-
# Check if Socket.IO server is already running
|
|
376
|
-
server_running = _check_socketio_server_running(socketio_port, logger)
|
|
377
|
-
|
|
378
|
-
if server_running:
|
|
379
|
-
print(f"✅ Socket.IO server already running on port {socketio_port}")
|
|
380
|
-
|
|
381
|
-
# Check if it's managed by our daemon
|
|
382
|
-
daemon_script = get_package_root() / "scripts" / "socketio_daemon.py"
|
|
383
|
-
if daemon_script.exists():
|
|
384
|
-
status_result = subprocess.run(
|
|
385
|
-
[sys.executable, str(daemon_script), "status"],
|
|
386
|
-
capture_output=True,
|
|
387
|
-
text=True
|
|
388
|
-
)
|
|
389
|
-
if "is running" in status_result.stdout:
|
|
390
|
-
print(f" (Managed by Python daemon)")
|
|
391
|
-
|
|
392
|
-
print(f"📊 Dashboard: {dashboard_url}")
|
|
393
|
-
|
|
394
|
-
# Open browser with static HTML file
|
|
395
|
-
try:
|
|
396
|
-
# Check if we should suppress browser opening (for tests)
|
|
397
|
-
if os.environ.get('CLAUDE_MPM_NO_BROWSER') != '1':
|
|
398
|
-
print(f"🌐 Opening dashboard in browser...")
|
|
399
|
-
open_in_browser_tab(dashboard_url, logger)
|
|
400
|
-
logger.info(f"Socket.IO dashboard opened: {dashboard_url}")
|
|
401
|
-
else:
|
|
402
|
-
print(f"🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)")
|
|
403
|
-
logger.info(f"Browser opening suppressed by environment variable")
|
|
404
|
-
return True, True
|
|
405
|
-
except Exception as e:
|
|
406
|
-
logger.warning(f"Failed to open browser: {e}")
|
|
407
|
-
print(f"⚠️ Could not open browser automatically")
|
|
408
|
-
print(f"📊 Please open manually: {dashboard_url}")
|
|
409
|
-
return True, False
|
|
410
|
-
else:
|
|
411
|
-
# Start standalone Socket.IO server
|
|
412
|
-
print(f"🔧 Starting Socket.IO server on port {socketio_port}...")
|
|
413
|
-
server_started = _start_standalone_socketio_server(socketio_port, logger)
|
|
414
|
-
|
|
415
|
-
if server_started:
|
|
416
|
-
print(f"✅ Socket.IO server started successfully")
|
|
417
|
-
print(f"📊 Dashboard: {dashboard_url}")
|
|
418
|
-
|
|
419
|
-
# Final verification that server is responsive
|
|
420
|
-
final_check_passed = False
|
|
421
|
-
for i in range(3):
|
|
422
|
-
if _check_socketio_server_running(socketio_port, logger):
|
|
423
|
-
final_check_passed = True
|
|
424
|
-
break
|
|
425
|
-
time.sleep(1)
|
|
426
|
-
|
|
427
|
-
if not final_check_passed:
|
|
428
|
-
logger.warning("Server started but final connectivity check failed")
|
|
429
|
-
print(f"⚠️ Server may still be initializing. Dashboard should work once fully ready.")
|
|
430
|
-
|
|
431
|
-
# Open browser with static HTML file
|
|
432
|
-
try:
|
|
433
|
-
# Check if we should suppress browser opening (for tests)
|
|
434
|
-
if os.environ.get('CLAUDE_MPM_NO_BROWSER') != '1':
|
|
435
|
-
print(f"🌐 Opening dashboard in browser...")
|
|
436
|
-
open_in_browser_tab(dashboard_url, logger)
|
|
437
|
-
logger.info(f"Socket.IO dashboard opened: {dashboard_url}")
|
|
438
|
-
else:
|
|
439
|
-
print(f"🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)")
|
|
440
|
-
logger.info(f"Browser opening suppressed by environment variable")
|
|
441
|
-
return True, True
|
|
442
|
-
except Exception as e:
|
|
443
|
-
logger.warning(f"Failed to open browser: {e}")
|
|
444
|
-
print(f"⚠️ Could not open browser automatically")
|
|
445
|
-
print(f"📊 Please open manually: {dashboard_url}")
|
|
446
|
-
return True, False
|
|
447
|
-
else:
|
|
448
|
-
print(f"❌ Failed to start Socket.IO server")
|
|
449
|
-
print(f"💡 Troubleshooting tips:")
|
|
450
|
-
print(f" - Check if port {socketio_port} is already in use")
|
|
451
|
-
print(f" - Verify Socket.IO dependencies: pip install python-socketio aiohttp")
|
|
452
|
-
print(f" - Try a different port with --websocket-port")
|
|
453
|
-
return False, False
|
|
454
|
-
|
|
455
|
-
except Exception as e:
|
|
456
|
-
logger.error(f"Failed to launch Socket.IO monitor: {e}")
|
|
457
|
-
print(f"❌ Failed to launch Socket.IO monitor: {e}")
|
|
458
|
-
return False, False
|
|
1057
|
+
"""Launch the Socket.IO monitoring dashboard (legacy compatibility)."""
|
|
1058
|
+
dashboard_manager = UnifiedDashboardManager(logger)
|
|
1059
|
+
success, server_info = dashboard_manager.start_server(port=port)
|
|
1060
|
+
|
|
1061
|
+
if success:
|
|
1062
|
+
# Open browser using UnifiedDashboardManager
|
|
1063
|
+
browser_opened = dashboard_manager.open_browser(server_info.url)
|
|
1064
|
+
return success, browser_opened
|
|
1065
|
+
|
|
1066
|
+
return False, False
|
|
459
1067
|
|
|
460
1068
|
|
|
461
1069
|
def _check_socketio_server_running(port, logger):
|
|
462
|
-
"""
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
WHY: We need to detect existing servers to avoid conflicts and provide
|
|
466
|
-
seamless experience regardless of whether server is already running.
|
|
467
|
-
|
|
468
|
-
DESIGN DECISION: We try multiple endpoints and connection methods to ensure
|
|
469
|
-
robust detection. Some servers may be starting up and only partially ready.
|
|
470
|
-
Added retry logic to handle race conditions during server initialization.
|
|
471
|
-
|
|
472
|
-
Args:
|
|
473
|
-
port: Port number to check
|
|
474
|
-
logger: Logger instance for output
|
|
475
|
-
|
|
476
|
-
Returns:
|
|
477
|
-
bool: True if server is running and responding, False otherwise
|
|
478
|
-
"""
|
|
479
|
-
try:
|
|
480
|
-
import urllib.request
|
|
481
|
-
import urllib.error
|
|
482
|
-
import socket
|
|
483
|
-
|
|
484
|
-
# First, do a basic TCP connection check
|
|
485
|
-
try:
|
|
486
|
-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
487
|
-
s.settimeout(2.0) # Increased from 1.0s for slower connections
|
|
488
|
-
result = s.connect_ex(('127.0.0.1', port))
|
|
489
|
-
if result != 0:
|
|
490
|
-
logger.debug(f"TCP connection to port {port} failed (server not started yet)")
|
|
491
|
-
return False
|
|
492
|
-
except Exception as e:
|
|
493
|
-
logger.debug(f"TCP socket check failed for port {port}: {e}")
|
|
494
|
-
return False
|
|
495
|
-
|
|
496
|
-
# If TCP connection succeeds, try HTTP health check with retries
|
|
497
|
-
# WHY: Even when TCP is accepting connections, the HTTP handler may not be ready
|
|
498
|
-
max_retries = 3
|
|
499
|
-
for retry in range(max_retries):
|
|
500
|
-
try:
|
|
501
|
-
response = urllib.request.urlopen(f'http://localhost:{port}/status', timeout=10) # Increased from 5s to 10s
|
|
502
|
-
|
|
503
|
-
if response.getcode() == 200:
|
|
504
|
-
content = response.read().decode()
|
|
505
|
-
logger.debug(f"✅ Socket.IO server health check passed on port {port} (attempt {retry + 1})")
|
|
506
|
-
logger.debug(f"📄 Server response: {content[:100]}...")
|
|
507
|
-
return True
|
|
508
|
-
else:
|
|
509
|
-
logger.debug(f"⚠️ HTTP response code {response.getcode()} from port {port} (attempt {retry + 1})")
|
|
510
|
-
if retry < max_retries - 1:
|
|
511
|
-
time.sleep(0.5) # Brief pause before retry
|
|
512
|
-
|
|
513
|
-
except urllib.error.HTTPError as e:
|
|
514
|
-
logger.debug(f"⚠️ HTTP error {e.code} from server on port {port} (attempt {retry + 1})")
|
|
515
|
-
if retry < max_retries - 1 and e.code in [404, 503]: # Server starting but not ready
|
|
516
|
-
logger.debug("Server appears to be starting, retrying...")
|
|
517
|
-
time.sleep(0.5)
|
|
518
|
-
continue
|
|
519
|
-
return False
|
|
520
|
-
except urllib.error.URLError as e:
|
|
521
|
-
logger.debug(f"⚠️ URL error connecting to port {port} (attempt {retry + 1}): {e.reason}")
|
|
522
|
-
if retry < max_retries - 1:
|
|
523
|
-
logger.debug("Connection refused - server may still be initializing, retrying...")
|
|
524
|
-
time.sleep(0.5)
|
|
525
|
-
continue
|
|
526
|
-
return False
|
|
527
|
-
|
|
528
|
-
# All retries exhausted
|
|
529
|
-
logger.debug(f"Health check failed after {max_retries} attempts - server not fully ready")
|
|
530
|
-
return False
|
|
531
|
-
|
|
532
|
-
except (ConnectionError, OSError) as e:
|
|
533
|
-
logger.debug(f"🔌 Connection error checking port {port}: {e}")
|
|
534
|
-
except Exception as e:
|
|
535
|
-
logger.debug(f"❌ Unexpected error checking Socket.IO server on port {port}: {e}")
|
|
536
|
-
|
|
537
|
-
return False
|
|
1070
|
+
"""Check if a Socket.IO server is running on the specified port (legacy compatibility)."""
|
|
1071
|
+
dashboard_manager = UnifiedDashboardManager(logger)
|
|
1072
|
+
return dashboard_manager.is_server_running(port)
|
|
538
1073
|
|
|
539
1074
|
|
|
540
1075
|
def _start_standalone_socketio_server(port, logger):
|
|
541
|
-
"""
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
of the Claude session. This allows users to monitor multiple sessions and
|
|
546
|
-
keeps the dashboard available even when Claude isn't running.
|
|
547
|
-
|
|
548
|
-
DESIGN DECISION: We use a pure Python daemon script to manage the server
|
|
549
|
-
process. This avoids Node.js dependencies (like PM2) and provides proper
|
|
550
|
-
process management with PID tracking.
|
|
551
|
-
|
|
552
|
-
Args:
|
|
553
|
-
port: Port number for the server
|
|
554
|
-
logger: Logger instance for output
|
|
555
|
-
|
|
556
|
-
Returns:
|
|
557
|
-
bool: True if server started successfully, False otherwise
|
|
558
|
-
"""
|
|
559
|
-
try:
|
|
560
|
-
from ...deployment_paths import get_scripts_dir
|
|
561
|
-
import subprocess
|
|
562
|
-
|
|
563
|
-
# Get path to daemon script in package
|
|
564
|
-
daemon_script = get_package_root() / "scripts" / "socketio_daemon.py"
|
|
565
|
-
|
|
566
|
-
if not daemon_script.exists():
|
|
567
|
-
logger.error(f"Socket.IO daemon script not found: {daemon_script}")
|
|
568
|
-
return False
|
|
569
|
-
|
|
570
|
-
logger.info(f"Starting Socket.IO server daemon on port {port}")
|
|
571
|
-
|
|
572
|
-
# Start the daemon
|
|
573
|
-
result = subprocess.run(
|
|
574
|
-
[sys.executable, str(daemon_script), "start"],
|
|
575
|
-
capture_output=True,
|
|
576
|
-
text=True
|
|
577
|
-
)
|
|
578
|
-
|
|
579
|
-
if result.returncode != 0:
|
|
580
|
-
logger.error(f"Failed to start Socket.IO daemon: {result.stderr}")
|
|
581
|
-
return False
|
|
582
|
-
|
|
583
|
-
# Wait for server to be ready with longer timeouts and progressive delays
|
|
584
|
-
# WHY: Socket.IO server startup involves complex async initialization:
|
|
585
|
-
# 1. Thread creation (~0.1s)
|
|
586
|
-
# 2. Event loop setup (~1s)
|
|
587
|
-
# 3. aiohttp server binding (~2-5s)
|
|
588
|
-
# 4. Socket.IO service initialization (~1-3s)
|
|
589
|
-
# Total: up to 15+ seconds for full readiness (especially on Python 3.13)
|
|
590
|
-
max_attempts = 30 # Increased from 20 to handle Python 3.13 slower initialization
|
|
591
|
-
initial_delay = 1.0 # Increased from 0.5s to give daemon more time to fork
|
|
592
|
-
max_delay = 3.0 # Increased from 2.0s for slower systems
|
|
593
|
-
|
|
594
|
-
logger.info(f"Waiting up to {max_attempts * max_delay} seconds for server to be fully ready...")
|
|
595
|
-
|
|
596
|
-
# Give the daemon initial time to fork and start before checking
|
|
597
|
-
logger.debug("Allowing initial daemon startup time...")
|
|
598
|
-
time.sleep(0.5)
|
|
599
|
-
|
|
600
|
-
for attempt in range(max_attempts):
|
|
601
|
-
# Progressive delay - start fast, then slow down for socket binding
|
|
602
|
-
if attempt < 5:
|
|
603
|
-
delay = initial_delay
|
|
604
|
-
else:
|
|
605
|
-
delay = min(max_delay, initial_delay + (attempt - 5) * 0.2)
|
|
606
|
-
|
|
607
|
-
logger.debug(f"Checking server readiness (attempt {attempt + 1}/{max_attempts}, waiting {delay}s)")
|
|
608
|
-
|
|
609
|
-
# Give the daemon process time to initialize and bind to the socket
|
|
610
|
-
time.sleep(delay)
|
|
611
|
-
|
|
612
|
-
# Check if the daemon server is accepting connections
|
|
613
|
-
if _check_socketio_server_running(port, logger):
|
|
614
|
-
logger.info(f"✅ Standalone Socket.IO server started successfully on port {port}")
|
|
615
|
-
logger.info(f"🕐 Server ready after {attempt + 1} attempts ({(attempt + 1) * delay:.1f}s)")
|
|
616
|
-
return True
|
|
617
|
-
else:
|
|
618
|
-
logger.debug(f"Server not yet accepting connections on attempt {attempt + 1}")
|
|
619
|
-
|
|
620
|
-
logger.error(f"❌ Socket.IO server health check failed after {max_attempts} attempts ({max_attempts * max_delay:.1f}s)")
|
|
621
|
-
logger.warning(f"⏱️ Server may still be starting - initialization can take 15+ seconds on some systems")
|
|
622
|
-
logger.warning(f"💡 The daemon process might be running but not yet accepting HTTP connections")
|
|
623
|
-
logger.error(f"🔧 Troubleshooting steps:")
|
|
624
|
-
logger.error(f" - Wait a few more seconds and try again")
|
|
625
|
-
logger.error(f" - Check for port conflicts: lsof -i :{port}")
|
|
626
|
-
logger.error(f" - Try a different port with --websocket-port")
|
|
627
|
-
logger.error(f" - Verify dependencies: pip install python-socketio aiohttp")
|
|
628
|
-
return False
|
|
629
|
-
|
|
630
|
-
except Exception as e:
|
|
631
|
-
logger.error(f"❌ Failed to start standalone Socket.IO server: {e}")
|
|
632
|
-
import traceback
|
|
633
|
-
logger.error(f"📋 Stack trace: {traceback.format_exc()}")
|
|
634
|
-
logger.error(f"💡 This may be a dependency issue - try: pip install python-socketio aiohttp")
|
|
635
|
-
return False
|
|
636
|
-
|
|
1076
|
+
"""Start a standalone Socket.IO server (legacy compatibility)."""
|
|
1077
|
+
dashboard_manager = UnifiedDashboardManager(logger)
|
|
1078
|
+
success, _ = dashboard_manager.start_server(port=port)
|
|
1079
|
+
return success
|
|
637
1080
|
|
|
638
1081
|
|
|
639
1082
|
def open_in_browser_tab(url, logger):
|
|
640
|
-
"""
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
""
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
# This is a best-effort approach for common browsers
|
|
668
|
-
webbrowser.get().open(url, new=0) # new=0 tries to reuse existing window
|
|
669
|
-
logger.info("Attempted Linux browser tab reuse")
|
|
670
|
-
except Exception:
|
|
671
|
-
webbrowser.open(url, autoraise=True)
|
|
672
|
-
|
|
673
|
-
elif system == "windows":
|
|
674
|
-
# On Windows, try to use existing browser
|
|
675
|
-
try:
|
|
676
|
-
webbrowser.get().open(url, new=0) # new=0 tries to reuse existing window
|
|
677
|
-
logger.info("Attempted Windows browser tab reuse")
|
|
678
|
-
except Exception:
|
|
679
|
-
webbrowser.open(url, autoraise=True)
|
|
680
|
-
else:
|
|
681
|
-
# Unknown platform, use standard opening
|
|
682
|
-
webbrowser.open(url, autoraise=True)
|
|
683
|
-
|
|
684
|
-
except Exception as e:
|
|
685
|
-
logger.warning(f"Browser opening failed: {e}")
|
|
686
|
-
# Final fallback
|
|
687
|
-
webbrowser.open(url)
|
|
1083
|
+
"""Open URL in browser, attempting to reuse existing tabs when possible."""
|
|
1084
|
+
manager = UnifiedDashboardManager(logger)
|
|
1085
|
+
return manager.open_browser(url)
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
def _check_claude_json_memory(args, logger):
|
|
1089
|
+
"""Check .claude.json file size and warn about memory issues."""
|
|
1090
|
+
# Use new StartupCheckerService
|
|
1091
|
+
from ...core.config import Config
|
|
1092
|
+
|
|
1093
|
+
config_service = Config()
|
|
1094
|
+
checker = StartupCheckerService(config_service)
|
|
1095
|
+
resume_enabled = getattr(args, "mpm_resume", False)
|
|
1096
|
+
warning = checker.check_memory(resume_enabled)
|
|
1097
|
+
if warning:
|
|
1098
|
+
checker.display_warnings([warning])
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
def _check_configuration_health(logger):
|
|
1102
|
+
"""Check configuration health at startup and warn about issues."""
|
|
1103
|
+
# Use new StartupCheckerService
|
|
1104
|
+
from ...core.config import Config
|
|
1105
|
+
|
|
1106
|
+
config_service = Config()
|
|
1107
|
+
checker = StartupCheckerService(config_service)
|
|
1108
|
+
warnings = checker.check_configuration()
|
|
1109
|
+
checker.display_warnings(warnings)
|