claude-mpm 5.4.22__py3-none-any.whl → 5.6.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +374 -1257
- claude_mpm/agents/WORKFLOW.md +6 -253
- claude_mpm/agents/agent_loader.py +1 -1
- claude_mpm/agents/base_agent.json +31 -0
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agent_state_manager.py +10 -10
- claude_mpm/cli/commands/agents.py +11 -13
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/auto_configure.py +4 -4
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +621 -22
- claude_mpm/cli/commands/configure_agent_display.py +12 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +72 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +130 -16
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +32 -52
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +83 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +690 -386
- claude_mpm/cli/startup_display.py +74 -6
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +146 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +146 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +450 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +309 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +20 -249
- claude_mpm/commands/mpm-doctor.md +16 -21
- claude_mpm/commands/mpm-help.md +12 -205
- claude_mpm/commands/mpm-init.md +88 -506
- claude_mpm/commands/mpm-monitor.md +22 -401
- claude_mpm/commands/mpm-organize.md +70 -442
- claude_mpm/commands/mpm-postmortem.md +13 -107
- claude_mpm/commands/mpm-session-resume.md +20 -363
- claude_mpm/commands/mpm-status.md +13 -69
- claude_mpm/commands/mpm-ticket-view.md +60 -495
- claude_mpm/commands/mpm-version.md +13 -107
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +37 -26
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/framework/loaders/agent_loader.py +1 -1
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +61 -0
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_agent_registry.py +1 -1
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.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/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DR8nis88.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.RgBboRvH.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.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/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.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__/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/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +313 -99
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +206 -36
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -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__/container.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__/protocols.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 +67 -32
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +310 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +276 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_builder.py +3 -3
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +7 -7
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +39 -19
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +101 -75
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +23 -4
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
- claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
- claude_mpm/services/agents/startup_sync.py +27 -4
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/git/git_operations_service.py +8 -8
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +15 -3
- claude_mpm/services/monitor/server.py +571 -11
- claude_mpm/services/pm_skills_deployer.py +884 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/skills/git_skill_source_manager.py +281 -20
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +37 -6
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/core.py +262 -123
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +115 -4
- claude_mpm/utils/agent_filters.py +1 -1
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +86 -21
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +486 -145
- claude_mpm-5.4.22.dist-info/METADATA +0 -996
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
|
@@ -44,11 +44,14 @@ class ConfigConstants:
|
|
|
44
44
|
"startup": 60,
|
|
45
45
|
"graceful_shutdown": 30,
|
|
46
46
|
},
|
|
47
|
-
# Ports
|
|
47
|
+
# Ports (updated to use network_config.NetworkPorts defaults)
|
|
48
48
|
"ports": {
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
49
|
+
"monitor_default": 8765, # NetworkPorts.MONITOR_DEFAULT
|
|
50
|
+
"commander_default": 8766, # NetworkPorts.COMMANDER_DEFAULT
|
|
51
|
+
"dashboard_default": 8767, # NetworkPorts.DASHBOARD_DEFAULT
|
|
52
|
+
"socketio_default": 8768, # NetworkPorts.SOCKETIO_DEFAULT
|
|
53
|
+
"socketio_range_start": 8765, # NetworkPorts.PORT_RANGE_START
|
|
54
|
+
"socketio_range_end": 8785, # NetworkPorts.PORT_RANGE_END
|
|
52
55
|
},
|
|
53
56
|
# Cache settings
|
|
54
57
|
"cache": {
|
|
@@ -134,23 +137,70 @@ class ConfigConstants:
|
|
|
134
137
|
Get port value by type.
|
|
135
138
|
|
|
136
139
|
Args:
|
|
137
|
-
port_type: Type of port (e.g., 'socketio_default')
|
|
140
|
+
port_type: Type of port (e.g., 'socketio_default', 'monitor_default')
|
|
138
141
|
|
|
139
142
|
Returns:
|
|
140
143
|
Port number
|
|
141
144
|
"""
|
|
142
145
|
try:
|
|
146
|
+
# Try to get from unified config first
|
|
143
147
|
config = cls._get_config_service().config
|
|
144
148
|
|
|
149
|
+
if port_type == "monitor_default":
|
|
150
|
+
return (
|
|
151
|
+
config.network.monitor_port
|
|
152
|
+
if hasattr(config.network, "monitor_port")
|
|
153
|
+
else 8765
|
|
154
|
+
)
|
|
155
|
+
if port_type == "commander_default":
|
|
156
|
+
return (
|
|
157
|
+
config.network.commander_port
|
|
158
|
+
if hasattr(config.network, "commander_port")
|
|
159
|
+
else 8766
|
|
160
|
+
)
|
|
161
|
+
if port_type == "dashboard_default":
|
|
162
|
+
return (
|
|
163
|
+
config.network.dashboard_port
|
|
164
|
+
if hasattr(config.network, "dashboard_port")
|
|
165
|
+
else 8767
|
|
166
|
+
)
|
|
145
167
|
if port_type == "socketio_default":
|
|
146
|
-
return
|
|
168
|
+
return (
|
|
169
|
+
config.network.socketio_port
|
|
170
|
+
if hasattr(config.network, "socketio_port")
|
|
171
|
+
else 8768
|
|
172
|
+
)
|
|
147
173
|
if port_type == "socketio_range_start":
|
|
148
|
-
return
|
|
174
|
+
return (
|
|
175
|
+
config.network.socketio_port_range[0]
|
|
176
|
+
if hasattr(config.network, "socketio_port_range")
|
|
177
|
+
else 8765
|
|
178
|
+
)
|
|
149
179
|
if port_type == "socketio_range_end":
|
|
150
|
-
return
|
|
180
|
+
return (
|
|
181
|
+
config.network.socketio_port_range[1]
|
|
182
|
+
if hasattr(config.network, "socketio_port_range")
|
|
183
|
+
else 8785
|
|
184
|
+
)
|
|
151
185
|
return cls.DEFAULT_VALUES["ports"].get(port_type, 8765)
|
|
152
186
|
except Exception:
|
|
153
|
-
|
|
187
|
+
# Fallback to network_config.NetworkPorts or DEFAULT_VALUES
|
|
188
|
+
try:
|
|
189
|
+
from .network_config import NetworkPorts
|
|
190
|
+
|
|
191
|
+
port_map = {
|
|
192
|
+
"monitor_default": NetworkPorts.MONITOR_DEFAULT,
|
|
193
|
+
"commander_default": NetworkPorts.COMMANDER_DEFAULT,
|
|
194
|
+
"dashboard_default": NetworkPorts.DASHBOARD_DEFAULT,
|
|
195
|
+
"socketio_default": NetworkPorts.SOCKETIO_DEFAULT,
|
|
196
|
+
"socketio_range_start": NetworkPorts.PORT_RANGE_START,
|
|
197
|
+
"socketio_range_end": NetworkPorts.PORT_RANGE_END,
|
|
198
|
+
}
|
|
199
|
+
return port_map.get(
|
|
200
|
+
port_type, cls.DEFAULT_VALUES["ports"].get(port_type, 8765)
|
|
201
|
+
)
|
|
202
|
+
except Exception:
|
|
203
|
+
return cls.DEFAULT_VALUES["ports"].get(port_type, 8765)
|
|
154
204
|
|
|
155
205
|
@classmethod
|
|
156
206
|
def get_cache_setting(cls, setting_name: str) -> Any:
|
|
@@ -304,6 +354,21 @@ def get_socketio_port() -> int:
|
|
|
304
354
|
return ConfigConstants.get_port("socketio_default")
|
|
305
355
|
|
|
306
356
|
|
|
357
|
+
def get_monitor_port() -> int:
|
|
358
|
+
"""Get default monitor port."""
|
|
359
|
+
return ConfigConstants.get_port("monitor_default")
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def get_commander_port() -> int:
|
|
363
|
+
"""Get default commander port."""
|
|
364
|
+
return ConfigConstants.get_port("commander_default")
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def get_dashboard_port() -> int:
|
|
368
|
+
"""Get default dashboard port."""
|
|
369
|
+
return ConfigConstants.get_port("dashboard_default")
|
|
370
|
+
|
|
371
|
+
|
|
307
372
|
def get_cache_size() -> float:
|
|
308
373
|
"""Get default cache size in MB."""
|
|
309
374
|
return ConfigConstants.get_cache_setting("max_size_mb")
|
claude_mpm/core/constants.py
CHANGED
|
@@ -38,12 +38,36 @@ class SystemLimits:
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class NetworkConfig:
|
|
41
|
-
"""Network-related configuration constants.
|
|
41
|
+
"""Network-related configuration constants.
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
NOTE: Port defaults are now centralized in network_config.NetworkPorts.
|
|
44
|
+
This class maintains backward compatibility but delegates to NetworkPorts.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
# Import from network_config for single source of truth
|
|
48
|
+
# Lazy import to avoid circular dependencies
|
|
49
|
+
@property
|
|
50
|
+
def SOCKETIO_PORT_RANGE(self) -> Tuple[int, int]:
|
|
51
|
+
from .network_config import NetworkPorts
|
|
52
|
+
|
|
53
|
+
return (NetworkPorts.PORT_RANGE_START, NetworkPorts.PORT_RANGE_END)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def DEFAULT_SOCKETIO_PORT(self) -> int:
|
|
57
|
+
from .network_config import NetworkPorts
|
|
58
|
+
|
|
59
|
+
return NetworkPorts.SOCKETIO_DEFAULT
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def DEFAULT_DASHBOARD_PORT(self) -> int:
|
|
63
|
+
from .network_config import NetworkPorts
|
|
64
|
+
|
|
65
|
+
return NetworkPorts.DASHBOARD_DEFAULT
|
|
66
|
+
|
|
67
|
+
# Port ranges (module-level for backward compatibility)
|
|
68
|
+
SOCKETIO_PORT_RANGE: Tuple[int, int] = (8765, 8785) # Will be updated at runtime
|
|
69
|
+
DEFAULT_SOCKETIO_PORT = 8768 # Updated to match new default
|
|
70
|
+
DEFAULT_DASHBOARD_PORT = 8767 # Updated to match new default
|
|
47
71
|
|
|
48
72
|
# Connection timeouts (seconds)
|
|
49
73
|
CONNECTION_TIMEOUT = 5.0
|
|
@@ -303,18 +327,38 @@ DEFAULT_TIMEOUT = TimeoutConfig.DEFAULT_TIMEOUT
|
|
|
303
327
|
|
|
304
328
|
|
|
305
329
|
class NetworkPorts:
|
|
306
|
-
"""Network port configuration.
|
|
330
|
+
"""Network port configuration.
|
|
331
|
+
|
|
332
|
+
DEPRECATED: Use claude_mpm.core.network_config.NetworkPorts instead.
|
|
333
|
+
This class is maintained for backward compatibility.
|
|
334
|
+
"""
|
|
335
|
+
|
|
336
|
+
# Import from network_config for single source of truth
|
|
337
|
+
@classmethod
|
|
338
|
+
def _get_config(cls):
|
|
339
|
+
from .network_config import NetworkPorts as NewNetworkPorts
|
|
340
|
+
|
|
341
|
+
return NewNetworkPorts
|
|
342
|
+
|
|
343
|
+
# Delegate to new NetworkPorts
|
|
344
|
+
@property
|
|
345
|
+
def DEFAULT_SOCKETIO(self) -> int:
|
|
346
|
+
return self._get_config().SOCKETIO_DEFAULT
|
|
347
|
+
|
|
348
|
+
@property
|
|
349
|
+
def DEFAULT_DASHBOARD(self) -> int:
|
|
350
|
+
return self._get_config().DASHBOARD_DEFAULT
|
|
307
351
|
|
|
308
|
-
#
|
|
309
|
-
DEFAULT_SOCKETIO =
|
|
310
|
-
DEFAULT_DASHBOARD =
|
|
311
|
-
PORT_RANGE_START =
|
|
312
|
-
PORT_RANGE_END =
|
|
352
|
+
# Keep class-level attributes for compatibility
|
|
353
|
+
DEFAULT_SOCKETIO = 8768 # Updated to match network_config
|
|
354
|
+
DEFAULT_DASHBOARD = 8767 # Updated to match network_config
|
|
355
|
+
PORT_RANGE_START = 8765
|
|
356
|
+
PORT_RANGE_END = 8785
|
|
313
357
|
|
|
314
358
|
@classmethod
|
|
315
359
|
def get_port_range(cls) -> range:
|
|
316
360
|
"""Get the valid port range."""
|
|
317
|
-
return
|
|
361
|
+
return cls._get_config().get_port_range()
|
|
318
362
|
|
|
319
363
|
|
|
320
364
|
class ProjectPaths:
|
|
@@ -118,7 +118,7 @@ class AgentLoader:
|
|
|
118
118
|
"""Discover local JSON agent templates.
|
|
119
119
|
|
|
120
120
|
NOTE: This method is kept for backward compatibility but is deprecated.
|
|
121
|
-
The new architecture uses SOURCE (~/.claude-mpm/cache/
|
|
121
|
+
The new architecture uses SOURCE (~/.claude-mpm/cache/agents/)
|
|
122
122
|
and DEPLOYMENT (.claude/agents/) locations only.
|
|
123
123
|
|
|
124
124
|
Returns:
|
|
@@ -88,39 +88,80 @@ class InstructionLoader:
|
|
|
88
88
|
self.packaged_loader.framework_last_modified
|
|
89
89
|
)
|
|
90
90
|
|
|
91
|
+
def _extract_version(self, file_content: str) -> int:
|
|
92
|
+
"""Extract version number from PM_INSTRUCTIONS_VERSION comment.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
file_content: Content of the file to extract version from
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Version number as integer, or 0 if not found
|
|
99
|
+
"""
|
|
100
|
+
import re
|
|
101
|
+
|
|
102
|
+
match = re.search(r"PM_INSTRUCTIONS_VERSION:\s*(\d+)", file_content)
|
|
103
|
+
if match:
|
|
104
|
+
return int(match.group(1))
|
|
105
|
+
return 0 # No version = oldest
|
|
106
|
+
|
|
91
107
|
def _load_filesystem_framework_instructions(self, content: Dict[str, Any]) -> None:
|
|
92
108
|
"""Load framework instructions from filesystem.
|
|
93
109
|
|
|
94
110
|
Priority order:
|
|
95
|
-
1. Deployed compiled file: .claude-mpm/PM_INSTRUCTIONS_DEPLOYED.md (
|
|
111
|
+
1. Deployed compiled file: .claude-mpm/PM_INSTRUCTIONS_DEPLOYED.md (if version >= source)
|
|
96
112
|
2. Source file (development): src/claude_mpm/agents/PM_INSTRUCTIONS.md
|
|
97
113
|
3. Legacy file (backward compat): src/claude_mpm/agents/INSTRUCTIONS.md
|
|
98
114
|
|
|
115
|
+
Version validation ensures deployed file is never stale compared to source.
|
|
116
|
+
|
|
99
117
|
Args:
|
|
100
118
|
content: Dictionary to update with framework instructions
|
|
101
119
|
"""
|
|
120
|
+
# Define source path for version checking
|
|
121
|
+
pm_instructions_path = (
|
|
122
|
+
self.framework_path / "src" / "claude_mpm" / "agents" / "PM_INSTRUCTIONS.md"
|
|
123
|
+
)
|
|
124
|
+
|
|
102
125
|
# PRIORITY 1: Check for compiled/deployed version in .claude-mpm/
|
|
103
126
|
# This is the merged PM_INSTRUCTIONS.md + WORKFLOW.md + MEMORY.md
|
|
104
127
|
deployed_path = self.current_dir / ".claude-mpm" / "PM_INSTRUCTIONS_DEPLOYED.md"
|
|
105
128
|
if deployed_path.exists():
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
|
|
129
|
+
# Validate version before using deployed file
|
|
130
|
+
deployed_content = deployed_path.read_text()
|
|
131
|
+
deployed_version = self._extract_version(deployed_content)
|
|
132
|
+
|
|
133
|
+
# Check source version for comparison
|
|
134
|
+
if pm_instructions_path.exists():
|
|
135
|
+
source_content = pm_instructions_path.read_text()
|
|
136
|
+
source_version = self._extract_version(source_content)
|
|
137
|
+
|
|
138
|
+
if deployed_version < source_version:
|
|
139
|
+
self.logger.warning(
|
|
140
|
+
f"Deployed PM instructions v{deployed_version:04d} is stale, "
|
|
141
|
+
f"source is v{source_version:04d}. Using source instead."
|
|
142
|
+
)
|
|
143
|
+
# Fall through to source loading - don't return early
|
|
144
|
+
else:
|
|
145
|
+
# Version OK, use deployed
|
|
146
|
+
content["framework_instructions"] = deployed_content
|
|
147
|
+
content["loaded"] = True
|
|
148
|
+
self.logger.info(
|
|
149
|
+
f"Loaded PM_INSTRUCTIONS_DEPLOYED.md v{deployed_version:04d} from .claude-mpm/"
|
|
150
|
+
)
|
|
151
|
+
return # Stop here - deployed version is current
|
|
152
|
+
else:
|
|
153
|
+
# Source doesn't exist, use deployed even without version check
|
|
154
|
+
content["framework_instructions"] = deployed_content
|
|
111
155
|
content["loaded"] = True
|
|
112
156
|
self.logger.info("Loaded PM_INSTRUCTIONS_DEPLOYED.md from .claude-mpm/")
|
|
113
|
-
return
|
|
157
|
+
return
|
|
114
158
|
|
|
115
159
|
# PRIORITY 2: Development mode - load from source PM_INSTRUCTIONS.md
|
|
116
|
-
pm_instructions_path = (
|
|
117
|
-
self.framework_path / "src" / "claude_mpm" / "agents" / "PM_INSTRUCTIONS.md"
|
|
118
|
-
)
|
|
119
160
|
framework_instructions_path = (
|
|
120
161
|
self.framework_path / "src" / "claude_mpm" / "agents" / "INSTRUCTIONS.md"
|
|
121
162
|
)
|
|
122
163
|
|
|
123
|
-
# Try loading new consolidated file
|
|
164
|
+
# Try loading new consolidated file (pm_instructions_path already defined above)
|
|
124
165
|
if pm_instructions_path.exists():
|
|
125
166
|
loaded_content = self.file_loader.try_load_file(
|
|
126
167
|
pm_instructions_path, "source PM_INSTRUCTIONS.md (development mode)"
|
claude_mpm/core/hook_manager.py
CHANGED
|
@@ -16,13 +16,15 @@ import contextlib
|
|
|
16
16
|
import json
|
|
17
17
|
import os
|
|
18
18
|
import queue
|
|
19
|
-
import subprocess
|
|
19
|
+
import subprocess # nosec B404
|
|
20
20
|
import threading
|
|
21
21
|
import uuid
|
|
22
22
|
from datetime import datetime, timezone
|
|
23
23
|
from typing import Any, Dict, Optional
|
|
24
24
|
|
|
25
25
|
from ..core.logger import get_logger
|
|
26
|
+
from ..services.event_bus.event_bus import EventBus
|
|
27
|
+
from ..services.event_log import get_event_log
|
|
26
28
|
from .hook_error_memory import get_hook_error_memory
|
|
27
29
|
from .hook_performance_config import get_hook_performance_config
|
|
28
30
|
from .unified_paths import get_package_root
|
|
@@ -46,6 +48,10 @@ class HookManager:
|
|
|
46
48
|
# Initialize error memory for tracking and preventing repeated errors
|
|
47
49
|
self.error_memory = get_hook_error_memory()
|
|
48
50
|
|
|
51
|
+
# Initialize event log and event bus for event-driven architecture
|
|
52
|
+
self.event_log = get_event_log()
|
|
53
|
+
self.event_bus = EventBus.get_instance()
|
|
54
|
+
|
|
49
55
|
# Initialize background hook processing for async execution
|
|
50
56
|
self.performance_config = get_hook_performance_config()
|
|
51
57
|
queue_config = self.performance_config.get_queue_config()
|
|
@@ -100,6 +106,45 @@ class HookManager:
|
|
|
100
106
|
self.background_thread.start()
|
|
101
107
|
self.logger.debug("Started background hook processor thread")
|
|
102
108
|
|
|
109
|
+
def _publish_error_event(
|
|
110
|
+
self, hook_type: str, error_info: Dict[str, str], suggestion: str
|
|
111
|
+
):
|
|
112
|
+
"""Publish hook error event to event log and event bus.
|
|
113
|
+
|
|
114
|
+
WHY publish events:
|
|
115
|
+
- Decouple error detection from error handling
|
|
116
|
+
- Enable autotodos CLI to read from persistent event log
|
|
117
|
+
- Support real-time notifications via event bus
|
|
118
|
+
- Maintain audit trail of all hook errors
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
hook_type: Type of hook that failed
|
|
122
|
+
error_info: Error information from error detection
|
|
123
|
+
suggestion: Fix suggestion from error memory
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
# Prepare event payload
|
|
127
|
+
payload = {
|
|
128
|
+
"error_type": error_info["type"],
|
|
129
|
+
"hook_type": hook_type,
|
|
130
|
+
"details": error_info.get("details", ""),
|
|
131
|
+
"full_message": error_info.get("match", ""),
|
|
132
|
+
"suggested_fix": suggestion,
|
|
133
|
+
"source": "hook_manager",
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
# Publish to event log (persistent storage)
|
|
137
|
+
self.event_log.append_event(
|
|
138
|
+
event_type="autotodo.error", payload=payload, status="pending"
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Publish to event bus (real-time listeners)
|
|
142
|
+
self.event_bus.publish("autotodo.error", payload)
|
|
143
|
+
|
|
144
|
+
except Exception as e:
|
|
145
|
+
# Don't let event publishing break hook processing
|
|
146
|
+
self.logger.debug(f"Failed to publish error event: {e}")
|
|
147
|
+
|
|
103
148
|
def _execute_hook_sync(self, hook_data: Dict[str, Any]):
|
|
104
149
|
"""Execute a single hook synchronously in the background thread with error detection.
|
|
105
150
|
|
|
@@ -141,7 +186,7 @@ class HookManager:
|
|
|
141
186
|
env["CLAUDE_MPM_HOOK_DEBUG"] = "true"
|
|
142
187
|
|
|
143
188
|
# Execute with timeout in background thread
|
|
144
|
-
result = subprocess.run(
|
|
189
|
+
result = subprocess.run( # nosec B603 B607
|
|
145
190
|
["python", str(self.hook_handler_path)],
|
|
146
191
|
input=event_json,
|
|
147
192
|
text=True,
|
|
@@ -157,7 +202,7 @@ class HookManager:
|
|
|
157
202
|
)
|
|
158
203
|
|
|
159
204
|
if error_info:
|
|
160
|
-
# Record the error
|
|
205
|
+
# Record the error in memory (for skipping repeated failures)
|
|
161
206
|
self.error_memory.record_error(error_info, hook_type)
|
|
162
207
|
|
|
163
208
|
# Get fix suggestion
|
|
@@ -165,6 +210,9 @@ class HookManager:
|
|
|
165
210
|
|
|
166
211
|
# Log error with suggestion
|
|
167
212
|
self.logger.warning(f"Hook {hook_type} error detected:\n{suggestion}")
|
|
213
|
+
|
|
214
|
+
# Publish event to event log for autotodos processing
|
|
215
|
+
self._publish_error_event(hook_type, error_info, suggestion)
|
|
168
216
|
elif result.returncode != 0:
|
|
169
217
|
# Non-zero return without detected pattern
|
|
170
218
|
self.logger.debug(f"Hook {hook_type} returned code {result.returncode}")
|
|
@@ -12,7 +12,7 @@ of InteractiveSession without circular dependency issues.
|
|
|
12
12
|
|
|
13
13
|
import contextlib
|
|
14
14
|
import os
|
|
15
|
-
import subprocess
|
|
15
|
+
import subprocess # nosec B404
|
|
16
16
|
import uuid
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
|
|
@@ -143,11 +143,12 @@ class InteractiveSession:
|
|
|
143
143
|
Tuple of (success, environment_dict)
|
|
144
144
|
"""
|
|
145
145
|
try:
|
|
146
|
-
#
|
|
147
|
-
|
|
148
|
-
|
|
146
|
+
# NOTE: System agents are deployed via reconciliation during startup.
|
|
147
|
+
# The reconciliation process respects user configuration and handles
|
|
148
|
+
# both native and custom mode deployment. No need to call setup_agents() here.
|
|
149
149
|
|
|
150
|
-
# Deploy project-specific agents
|
|
150
|
+
# Deploy project-specific agents from .claude-mpm/agents/
|
|
151
|
+
# This is separate from system agents and handles user-defined agents
|
|
151
152
|
self.runner.deploy_project_agents_to_claude()
|
|
152
153
|
|
|
153
154
|
# Build command
|
|
@@ -359,19 +360,19 @@ class InteractiveSession:
|
|
|
359
360
|
osm = self.runner.framework_loader.output_style_manager
|
|
360
361
|
if osm:
|
|
361
362
|
if osm.claude_version and osm.supports_output_styles():
|
|
362
|
-
# Check if
|
|
363
|
+
# Check if Claude MPM style is active
|
|
363
364
|
settings_file = osm.settings_file
|
|
364
365
|
if settings_file.exists():
|
|
365
366
|
import json
|
|
366
367
|
|
|
367
368
|
settings = json.loads(settings_file.read_text())
|
|
368
369
|
active_style = settings.get("activeOutputStyle")
|
|
369
|
-
if active_style
|
|
370
|
-
return "Output Style:
|
|
370
|
+
if active_style in ("Claude MPM", "Claude MPM Teacher"):
|
|
371
|
+
return f"Output Style: {active_style} ✅"
|
|
371
372
|
return f"Output Style: {active_style or 'none'}"
|
|
372
373
|
return "Output Style: Available"
|
|
373
374
|
return "Output Style: Injected (legacy)"
|
|
374
|
-
except Exception:
|
|
375
|
+
except Exception: # nosec B110
|
|
375
376
|
pass
|
|
376
377
|
return None
|
|
377
378
|
|
|
@@ -582,7 +583,7 @@ class InteractiveSession:
|
|
|
582
583
|
)
|
|
583
584
|
|
|
584
585
|
# This will not return if successful
|
|
585
|
-
os.execvpe(cmd[0], cmd, env)
|
|
586
|
+
os.execvpe(cmd[0], cmd, env) # nosec B606
|
|
586
587
|
return False # Only reached on failure
|
|
587
588
|
|
|
588
589
|
def _launch_subprocess_mode(self, cmd: list, env: dict) -> bool:
|
|
@@ -641,7 +642,7 @@ class InteractiveSession:
|
|
|
641
642
|
cmd = environment["command"]
|
|
642
643
|
env = environment["environment"]
|
|
643
644
|
|
|
644
|
-
result = subprocess.run(
|
|
645
|
+
result = subprocess.run( # nosec B603
|
|
645
646
|
cmd, stdin=None, stdout=None, stderr=None, env=env, check=False
|
|
646
647
|
)
|
|
647
648
|
|
claude_mpm/core/logger.py
CHANGED
|
@@ -214,19 +214,22 @@ def setup_logging(
|
|
|
214
214
|
|
|
215
215
|
# Console handler
|
|
216
216
|
if console_output:
|
|
217
|
+
# MUST use stderr to avoid corrupting hook JSON output
|
|
218
|
+
# WHY stderr: Hook handlers output JSON to stdout. Logging to stdout
|
|
219
|
+
# corrupts this JSON and causes "hook error" messages from Claude Code.
|
|
217
220
|
if use_streaming:
|
|
218
221
|
# Use streaming handler for single-line INFO messages
|
|
219
|
-
console_handler = StreamingHandler(sys.
|
|
222
|
+
console_handler = StreamingHandler(sys.stderr)
|
|
220
223
|
console_handler.setFormatter(simple_formatter)
|
|
221
224
|
elif use_rich and not json_format:
|
|
222
225
|
# Rich support has been removed, use standard handler
|
|
223
|
-
console_handler = logging.StreamHandler(sys.
|
|
226
|
+
console_handler = logging.StreamHandler(sys.stderr)
|
|
224
227
|
console_handler.setFormatter(simple_formatter)
|
|
225
228
|
else:
|
|
226
|
-
console_handler = logging.StreamHandler(sys.
|
|
229
|
+
console_handler = logging.StreamHandler(sys.stderr)
|
|
227
230
|
console_handler.setFormatter(formatter if json_format else simple_formatter)
|
|
228
231
|
|
|
229
|
-
console_handler.setLevel(
|
|
232
|
+
console_handler.setLevel(log_level) # Respect the requested log level
|
|
230
233
|
logger.addHandler(console_handler)
|
|
231
234
|
|
|
232
235
|
# File handler
|
|
@@ -263,7 +266,7 @@ def setup_logging(
|
|
|
263
266
|
if deleted_count > 0:
|
|
264
267
|
# Log to the new file handler that we're about to add
|
|
265
268
|
pass # Deletion count will be logged when logger is ready
|
|
266
|
-
except Exception:
|
|
269
|
+
except Exception: # nosec B110 - intentional: logging should not break app
|
|
267
270
|
pass # Ignore cleanup errors
|
|
268
271
|
|
|
269
272
|
# Also create a symlink to latest log (with thread safety)
|
|
@@ -305,7 +308,7 @@ def setup_logging(
|
|
|
305
308
|
# Fallback: try to create a regular file with reference to actual log
|
|
306
309
|
try:
|
|
307
310
|
latest_link.write_text(f"Latest log: {log_file.name}\n")
|
|
308
|
-
except Exception:
|
|
311
|
+
except Exception: # nosec B110 - intentional: logging should not break app
|
|
309
312
|
pass # Silently fail - logging should not break the application
|
|
310
313
|
except Exception as e:
|
|
311
314
|
# Catch any other unexpected errors to ensure logging doesn't break
|
|
@@ -381,15 +384,29 @@ def cleanup_old_mpm_logs(
|
|
|
381
384
|
try:
|
|
382
385
|
log_file.unlink()
|
|
383
386
|
deleted_count += 1
|
|
384
|
-
except Exception:
|
|
387
|
+
except Exception: # nosec B110 - intentional: log cleanup is best-effort
|
|
385
388
|
pass # Ignore deletion errors
|
|
386
389
|
|
|
387
390
|
return deleted_count
|
|
388
391
|
|
|
389
392
|
|
|
390
393
|
def get_logger(name: str) -> logging.Logger:
|
|
391
|
-
"""Get a logger instance.
|
|
392
|
-
|
|
394
|
+
"""Get a logger instance.
|
|
395
|
+
|
|
396
|
+
CRITICAL: Respects startup suppression mode (CRITICAL+1) to prevent
|
|
397
|
+
early INFO logs before setup_logging() is called.
|
|
398
|
+
"""
|
|
399
|
+
logger = logging.getLogger(f"claude_mpm.{name}")
|
|
400
|
+
|
|
401
|
+
# Check if root logger is suppressed (startup.py sets CRITICAL+1)
|
|
402
|
+
root_logger = logging.getLogger()
|
|
403
|
+
if root_logger.level > logging.CRITICAL:
|
|
404
|
+
# Suppression active - ensure this logger is also suppressed
|
|
405
|
+
logger.setLevel(logging.CRITICAL + 1)
|
|
406
|
+
logger.handlers = []
|
|
407
|
+
logger.propagate = False
|
|
408
|
+
|
|
409
|
+
return logger
|
|
393
410
|
|
|
394
411
|
|
|
395
412
|
def setup_streaming_logger(name: str, level: str = "INFO") -> logging.Logger:
|
claude_mpm/core/logging_utils.py
CHANGED
|
@@ -103,21 +103,47 @@ class LoggerFactory:
|
|
|
103
103
|
|
|
104
104
|
# Set up root logger
|
|
105
105
|
root_logger = logging.getLogger()
|
|
106
|
-
root_logger.setLevel(LoggingConfig.LEVELS.get(cls._log_level, logging.INFO))
|
|
107
106
|
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
107
|
+
# CRITICAL FIX: Respect existing root logger suppression
|
|
108
|
+
# If root logger is already set to CRITICAL+1 (suppressed by startup.py),
|
|
109
|
+
# don't override it. This prevents logging from appearing during startup
|
|
110
|
+
# before the CLI's setup_logging() runs.
|
|
111
|
+
current_level = root_logger.level
|
|
112
|
+
desired_level = LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
|
|
113
|
+
|
|
114
|
+
# Only set level if current is unset (0) or lower than desired
|
|
115
|
+
# CRITICAL+1 is 51, so this check preserves suppression
|
|
116
|
+
should_configure_logging = current_level == 0 or (
|
|
117
|
+
current_level < desired_level and current_level <= logging.CRITICAL
|
|
117
118
|
)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
|
|
120
|
+
if should_configure_logging:
|
|
121
|
+
root_logger.setLevel(desired_level)
|
|
122
|
+
# else: root logger is suppressed (CRITICAL+1), keep it suppressed
|
|
123
|
+
|
|
124
|
+
# Preserve FileHandlers (e.g., hooks logging), only remove StreamHandlers
|
|
125
|
+
root_logger.handlers = [
|
|
126
|
+
h for h in root_logger.handlers if isinstance(h, logging.FileHandler)
|
|
127
|
+
]
|
|
128
|
+
|
|
129
|
+
# CRITICAL FIX: Don't add handlers if logging is suppressed
|
|
130
|
+
# If root logger is at CRITICAL+1 (startup suppression), don't add any handlers
|
|
131
|
+
# This prevents early imports from logging before CLI setup_logging() runs
|
|
132
|
+
if should_configure_logging:
|
|
133
|
+
# Console handler - MUST use stderr to avoid corrupting hook JSON output
|
|
134
|
+
# WHY stderr: Hook handlers output JSON to stdout. Logging to stdout
|
|
135
|
+
# corrupts this JSON and causes "hook error" messages from Claude Code.
|
|
136
|
+
console_handler = logging.StreamHandler(sys.stderr)
|
|
137
|
+
console_handler.setLevel(
|
|
138
|
+
LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
|
|
139
|
+
)
|
|
140
|
+
console_formatter = logging.Formatter(
|
|
141
|
+
log_format or LoggingConfig.DEFAULT_FORMAT,
|
|
142
|
+
date_format or LoggingConfig.DATE_FORMAT,
|
|
143
|
+
)
|
|
144
|
+
console_handler.setFormatter(console_formatter)
|
|
145
|
+
root_logger.addHandler(console_handler)
|
|
146
|
+
cls._handlers["console"] = console_handler
|
|
121
147
|
|
|
122
148
|
# File handler (optional)
|
|
123
149
|
if log_to_file and cls._log_dir:
|