claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__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/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +2 -2
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +140 -905
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +330 -86
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +363 -220
- claude_mpm/cli/parser.py +24 -1156
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +124 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- 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 +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/built/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/built/dashboard.js +2 -0
- claude_mpm/dashboard/static/built/socket-client.js +2 -0
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +133 -53
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -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 +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -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/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 +159 -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 +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -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/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -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 +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- 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 +4 -3
- 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 +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +233 -199
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +30 -13
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +575 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +166 -64
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +185 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +19 -533
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
- claude_mpm-4.0.4.dist-info/RECORD +417 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- 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 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
| @@ -1,325 +0,0 @@ | |
| 1 | 
            -
            """Memory Guardian configuration for managing Claude Code memory usage.
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            This module provides configuration management for the MemoryGuardian service
         | 
| 4 | 
            -
            that monitors and manages Claude Code subprocess memory consumption.
         | 
| 5 | 
            -
             | 
| 6 | 
            -
            Design Principles:
         | 
| 7 | 
            -
            - Platform-agnostic configuration with OS-specific overrides
         | 
| 8 | 
            -
            - Environment-based configuration for different deployment scenarios
         | 
| 9 | 
            -
            - Flexible thresholds for memory monitoring
         | 
| 10 | 
            -
            - Support for both psutil and fallback monitoring methods
         | 
| 11 | 
            -
            """
         | 
| 12 | 
            -
             | 
| 13 | 
            -
            import os
         | 
| 14 | 
            -
            import platform
         | 
| 15 | 
            -
            from dataclasses import dataclass, field
         | 
| 16 | 
            -
            from pathlib import Path
         | 
| 17 | 
            -
            from typing import Dict, Any, Optional, List
         | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
            @dataclass
         | 
| 21 | 
            -
            class MemoryThresholds:
         | 
| 22 | 
            -
                """Memory threshold configuration in MB."""
         | 
| 23 | 
            -
                
         | 
| 24 | 
            -
                # Memory thresholds in MB (defaults for 24GB system)
         | 
| 25 | 
            -
                warning: int = 12288  # 12GB - Start monitoring closely
         | 
| 26 | 
            -
                critical: int = 15360  # 15GB - Consider restart
         | 
| 27 | 
            -
                emergency: int = 18432  # 18GB - Force restart
         | 
| 28 | 
            -
                
         | 
| 29 | 
            -
                # Percentage-based thresholds (as fallback when system memory is detected)
         | 
| 30 | 
            -
                warning_percent: float = 50.0  # 50% of system memory
         | 
| 31 | 
            -
                critical_percent: float = 65.0  # 65% of system memory
         | 
| 32 | 
            -
                emergency_percent: float = 75.0  # 75% of system memory
         | 
| 33 | 
            -
                
         | 
| 34 | 
            -
                def adjust_for_system_memory(self, total_memory_mb: int) -> None:
         | 
| 35 | 
            -
                    """Adjust thresholds based on available system memory."""
         | 
| 36 | 
            -
                    if total_memory_mb > 0:
         | 
| 37 | 
            -
                        self.warning = int(total_memory_mb * (self.warning_percent / 100))
         | 
| 38 | 
            -
                        self.critical = int(total_memory_mb * (self.critical_percent / 100))
         | 
| 39 | 
            -
                        self.emergency = int(total_memory_mb * (self.emergency_percent / 100))
         | 
| 40 | 
            -
                
         | 
| 41 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 42 | 
            -
                    """Convert thresholds to dictionary."""
         | 
| 43 | 
            -
                    return {
         | 
| 44 | 
            -
                        'warning_mb': self.warning,
         | 
| 45 | 
            -
                        'critical_mb': self.critical,
         | 
| 46 | 
            -
                        'emergency_mb': self.emergency,
         | 
| 47 | 
            -
                        'warning_percent': self.warning_percent,
         | 
| 48 | 
            -
                        'critical_percent': self.critical_percent,
         | 
| 49 | 
            -
                        'emergency_percent': self.emergency_percent
         | 
| 50 | 
            -
                    }
         | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
            @dataclass
         | 
| 54 | 
            -
            class RestartPolicy:
         | 
| 55 | 
            -
                """Configuration for process restart behavior."""
         | 
| 56 | 
            -
                
         | 
| 57 | 
            -
                # Restart attempts
         | 
| 58 | 
            -
                max_attempts: int = 3  # Maximum restart attempts before giving up
         | 
| 59 | 
            -
                attempt_window: int = 3600  # Window in seconds to count attempts (1 hour)
         | 
| 60 | 
            -
                
         | 
| 61 | 
            -
                # Cooldown periods
         | 
| 62 | 
            -
                initial_cooldown: int = 30  # Initial cooldown after restart (seconds)
         | 
| 63 | 
            -
                max_cooldown: int = 300  # Maximum cooldown period (5 minutes)
         | 
| 64 | 
            -
                cooldown_multiplier: float = 2.0  # Multiply cooldown on each retry
         | 
| 65 | 
            -
                
         | 
| 66 | 
            -
                # Graceful shutdown
         | 
| 67 | 
            -
                graceful_timeout: int = 30  # Time to wait for graceful shutdown (seconds)
         | 
| 68 | 
            -
                force_kill_timeout: int = 10  # Time to wait before SIGKILL after SIGTERM
         | 
| 69 | 
            -
                
         | 
| 70 | 
            -
                def get_cooldown(self, attempt: int) -> int:
         | 
| 71 | 
            -
                    """Calculate cooldown period for given attempt number."""
         | 
| 72 | 
            -
                    cooldown = self.initial_cooldown * (self.cooldown_multiplier ** (attempt - 1))
         | 
| 73 | 
            -
                    return min(int(cooldown), self.max_cooldown)
         | 
| 74 | 
            -
                
         | 
| 75 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 76 | 
            -
                    """Convert restart policy to dictionary."""
         | 
| 77 | 
            -
                    return {
         | 
| 78 | 
            -
                        'max_attempts': self.max_attempts,
         | 
| 79 | 
            -
                        'attempt_window': self.attempt_window,
         | 
| 80 | 
            -
                        'initial_cooldown': self.initial_cooldown,
         | 
| 81 | 
            -
                        'max_cooldown': self.max_cooldown,
         | 
| 82 | 
            -
                        'cooldown_multiplier': self.cooldown_multiplier,
         | 
| 83 | 
            -
                        'graceful_timeout': self.graceful_timeout,
         | 
| 84 | 
            -
                        'force_kill_timeout': self.force_kill_timeout
         | 
| 85 | 
            -
                    }
         | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
            @dataclass
         | 
| 89 | 
            -
            class MonitoringConfig:
         | 
| 90 | 
            -
                """Configuration for memory monitoring behavior."""
         | 
| 91 | 
            -
                
         | 
| 92 | 
            -
                # Check intervals (seconds)
         | 
| 93 | 
            -
                normal_interval: int = 30  # Normal check interval
         | 
| 94 | 
            -
                warning_interval: int = 15  # Check interval when in warning state
         | 
| 95 | 
            -
                critical_interval: int = 5  # Check interval when in critical state
         | 
| 96 | 
            -
                
         | 
| 97 | 
            -
                # Monitoring method preferences
         | 
| 98 | 
            -
                prefer_psutil: bool = True  # Prefer psutil if available
         | 
| 99 | 
            -
                fallback_methods: List[str] = field(default_factory=lambda: [
         | 
| 100 | 
            -
                    'platform_specific',  # Use OS-specific commands
         | 
| 101 | 
            -
                    'resource_module',    # Use resource module as last resort
         | 
| 102 | 
            -
                ])
         | 
| 103 | 
            -
                
         | 
| 104 | 
            -
                # Logging and reporting
         | 
| 105 | 
            -
                log_memory_stats: bool = True  # Log memory statistics
         | 
| 106 | 
            -
                log_interval: int = 300  # Log summary every 5 minutes
         | 
| 107 | 
            -
                detailed_logging: bool = False  # Enable detailed debug logging
         | 
| 108 | 
            -
                
         | 
| 109 | 
            -
                def get_check_interval(self, memory_state: str) -> int:
         | 
| 110 | 
            -
                    """Get check interval based on current memory state."""
         | 
| 111 | 
            -
                    if memory_state == 'critical':
         | 
| 112 | 
            -
                        return self.critical_interval
         | 
| 113 | 
            -
                    elif memory_state == 'warning':
         | 
| 114 | 
            -
                        return self.warning_interval
         | 
| 115 | 
            -
                    else:
         | 
| 116 | 
            -
                        return self.normal_interval
         | 
| 117 | 
            -
                
         | 
| 118 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 119 | 
            -
                    """Convert monitoring config to dictionary."""
         | 
| 120 | 
            -
                    return {
         | 
| 121 | 
            -
                        'normal_interval': self.normal_interval,
         | 
| 122 | 
            -
                        'warning_interval': self.warning_interval,
         | 
| 123 | 
            -
                        'critical_interval': self.critical_interval,
         | 
| 124 | 
            -
                        'prefer_psutil': self.prefer_psutil,
         | 
| 125 | 
            -
                        'fallback_methods': self.fallback_methods,
         | 
| 126 | 
            -
                        'log_memory_stats': self.log_memory_stats,
         | 
| 127 | 
            -
                        'log_interval': self.log_interval,
         | 
| 128 | 
            -
                        'detailed_logging': self.detailed_logging
         | 
| 129 | 
            -
                    }
         | 
| 130 | 
            -
             | 
| 131 | 
            -
             | 
| 132 | 
            -
            @dataclass
         | 
| 133 | 
            -
            class PlatformOverrides:
         | 
| 134 | 
            -
                """Platform-specific configuration overrides."""
         | 
| 135 | 
            -
                
         | 
| 136 | 
            -
                # macOS specific
         | 
| 137 | 
            -
                macos_use_activity_monitor: bool = False  # Use Activity Monitor data if available
         | 
| 138 | 
            -
                macos_memory_pressure_check: bool = True  # Check system memory pressure
         | 
| 139 | 
            -
                
         | 
| 140 | 
            -
                # Linux specific
         | 
| 141 | 
            -
                linux_use_proc: bool = True  # Use /proc filesystem
         | 
| 142 | 
            -
                linux_check_oom_score: bool = True  # Monitor OOM killer score
         | 
| 143 | 
            -
                
         | 
| 144 | 
            -
                # Windows specific
         | 
| 145 | 
            -
                windows_use_wmi: bool = True  # Use WMI for monitoring
         | 
| 146 | 
            -
                windows_use_performance_counter: bool = False  # Use performance counters
         | 
| 147 | 
            -
                
         | 
| 148 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 149 | 
            -
                    """Convert platform overrides to dictionary."""
         | 
| 150 | 
            -
                    return {
         | 
| 151 | 
            -
                        'macos_use_activity_monitor': self.macos_use_activity_monitor,
         | 
| 152 | 
            -
                        'macos_memory_pressure_check': self.macos_memory_pressure_check,
         | 
| 153 | 
            -
                        'linux_use_proc': self.linux_use_proc,
         | 
| 154 | 
            -
                        'linux_check_oom_score': self.linux_check_oom_score,
         | 
| 155 | 
            -
                        'windows_use_wmi': self.windows_use_wmi,
         | 
| 156 | 
            -
                        'windows_use_performance_counter': self.windows_use_performance_counter
         | 
| 157 | 
            -
                    }
         | 
| 158 | 
            -
             | 
| 159 | 
            -
             | 
| 160 | 
            -
            @dataclass
         | 
| 161 | 
            -
            class MemoryGuardianConfig:
         | 
| 162 | 
            -
                """Complete configuration for MemoryGuardian service."""
         | 
| 163 | 
            -
                
         | 
| 164 | 
            -
                # Core configurations
         | 
| 165 | 
            -
                thresholds: MemoryThresholds = field(default_factory=MemoryThresholds)
         | 
| 166 | 
            -
                restart_policy: RestartPolicy = field(default_factory=RestartPolicy)
         | 
| 167 | 
            -
                monitoring: MonitoringConfig = field(default_factory=MonitoringConfig)
         | 
| 168 | 
            -
                platform_overrides: PlatformOverrides = field(default_factory=PlatformOverrides)
         | 
| 169 | 
            -
                
         | 
| 170 | 
            -
                # Process configuration
         | 
| 171 | 
            -
                process_command: List[str] = field(default_factory=lambda: ['claude-code'])
         | 
| 172 | 
            -
                process_args: List[str] = field(default_factory=list)
         | 
| 173 | 
            -
                process_env: Dict[str, str] = field(default_factory=dict)
         | 
| 174 | 
            -
                working_directory: Optional[str] = None
         | 
| 175 | 
            -
                
         | 
| 176 | 
            -
                # Service configuration
         | 
| 177 | 
            -
                enabled: bool = True  # Enable memory guardian
         | 
| 178 | 
            -
                auto_start: bool = True  # Auto-start monitored process
         | 
| 179 | 
            -
                persist_state: bool = True  # Persist state across restarts
         | 
| 180 | 
            -
                state_file: Optional[str] = None  # State file path
         | 
| 181 | 
            -
                
         | 
| 182 | 
            -
                @classmethod
         | 
| 183 | 
            -
                def from_env(cls) -> 'MemoryGuardianConfig':
         | 
| 184 | 
            -
                    """Create configuration from environment variables."""
         | 
| 185 | 
            -
                    config = cls()
         | 
| 186 | 
            -
                    
         | 
| 187 | 
            -
                    # Memory thresholds
         | 
| 188 | 
            -
                    if warning := os.getenv('CLAUDE_MPM_MEMORY_WARNING_MB'):
         | 
| 189 | 
            -
                        config.thresholds.warning = int(warning)
         | 
| 190 | 
            -
                    if critical := os.getenv('CLAUDE_MPM_MEMORY_CRITICAL_MB'):
         | 
| 191 | 
            -
                        config.thresholds.critical = int(critical)
         | 
| 192 | 
            -
                    if emergency := os.getenv('CLAUDE_MPM_MEMORY_EMERGENCY_MB'):
         | 
| 193 | 
            -
                        config.thresholds.emergency = int(emergency)
         | 
| 194 | 
            -
                    
         | 
| 195 | 
            -
                    # Restart policy
         | 
| 196 | 
            -
                    if max_attempts := os.getenv('CLAUDE_MPM_RESTART_MAX_ATTEMPTS'):
         | 
| 197 | 
            -
                        config.restart_policy.max_attempts = int(max_attempts)
         | 
| 198 | 
            -
                    if cooldown := os.getenv('CLAUDE_MPM_RESTART_COOLDOWN'):
         | 
| 199 | 
            -
                        config.restart_policy.initial_cooldown = int(cooldown)
         | 
| 200 | 
            -
                    
         | 
| 201 | 
            -
                    # Monitoring intervals
         | 
| 202 | 
            -
                    if interval := os.getenv('CLAUDE_MPM_MONITOR_INTERVAL'):
         | 
| 203 | 
            -
                        config.monitoring.normal_interval = int(interval)
         | 
| 204 | 
            -
                    if log_interval := os.getenv('CLAUDE_MPM_LOG_INTERVAL'):
         | 
| 205 | 
            -
                        config.monitoring.log_interval = int(log_interval)
         | 
| 206 | 
            -
                    
         | 
| 207 | 
            -
                    # Service settings
         | 
| 208 | 
            -
                    config.enabled = os.getenv('CLAUDE_MPM_MEMORY_GUARDIAN_ENABLED', 'true').lower() == 'true'
         | 
| 209 | 
            -
                    config.auto_start = os.getenv('CLAUDE_MPM_AUTO_START', 'true').lower() == 'true'
         | 
| 210 | 
            -
                    
         | 
| 211 | 
            -
                    # Process command
         | 
| 212 | 
            -
                    if command := os.getenv('CLAUDE_MPM_PROCESS_COMMAND'):
         | 
| 213 | 
            -
                        config.process_command = command.split()
         | 
| 214 | 
            -
                    
         | 
| 215 | 
            -
                    return config
         | 
| 216 | 
            -
                
         | 
| 217 | 
            -
                @classmethod
         | 
| 218 | 
            -
                def for_development(cls) -> 'MemoryGuardianConfig':
         | 
| 219 | 
            -
                    """Configuration optimized for development."""
         | 
| 220 | 
            -
                    config = cls()
         | 
| 221 | 
            -
                    config.thresholds.warning = 8192  # 8GB for dev machines
         | 
| 222 | 
            -
                    config.thresholds.critical = 10240  # 10GB
         | 
| 223 | 
            -
                    config.thresholds.emergency = 12288  # 12GB
         | 
| 224 | 
            -
                    config.monitoring.normal_interval = 60  # Check less frequently
         | 
| 225 | 
            -
                    config.monitoring.detailed_logging = True
         | 
| 226 | 
            -
                    return config
         | 
| 227 | 
            -
                
         | 
| 228 | 
            -
                @classmethod
         | 
| 229 | 
            -
                def for_production(cls) -> 'MemoryGuardianConfig':
         | 
| 230 | 
            -
                    """Configuration optimized for production."""
         | 
| 231 | 
            -
                    config = cls()
         | 
| 232 | 
            -
                    config.monitoring.normal_interval = 30
         | 
| 233 | 
            -
                    config.monitoring.log_memory_stats = True
         | 
| 234 | 
            -
                    config.persist_state = True
         | 
| 235 | 
            -
                    config.restart_policy.max_attempts = 5
         | 
| 236 | 
            -
                    return config
         | 
| 237 | 
            -
                
         | 
| 238 | 
            -
                @classmethod
         | 
| 239 | 
            -
                def for_platform(cls, platform_name: Optional[str] = None) -> 'MemoryGuardianConfig':
         | 
| 240 | 
            -
                    """Get platform-specific configuration."""
         | 
| 241 | 
            -
                    if platform_name is None:
         | 
| 242 | 
            -
                        platform_name = platform.system().lower()
         | 
| 243 | 
            -
                    
         | 
| 244 | 
            -
                    config = cls()
         | 
| 245 | 
            -
                    
         | 
| 246 | 
            -
                    if platform_name == 'darwin':  # macOS
         | 
| 247 | 
            -
                        config.platform_overrides.macos_memory_pressure_check = True
         | 
| 248 | 
            -
                    elif platform_name == 'linux':
         | 
| 249 | 
            -
                        config.platform_overrides.linux_use_proc = True
         | 
| 250 | 
            -
                        config.platform_overrides.linux_check_oom_score = True
         | 
| 251 | 
            -
                    elif platform_name == 'windows':
         | 
| 252 | 
            -
                        config.platform_overrides.windows_use_wmi = True
         | 
| 253 | 
            -
                    
         | 
| 254 | 
            -
                    return config
         | 
| 255 | 
            -
                
         | 
| 256 | 
            -
                def to_dict(self) -> Dict[str, Any]:
         | 
| 257 | 
            -
                    """Convert configuration to dictionary."""
         | 
| 258 | 
            -
                    return {
         | 
| 259 | 
            -
                        'thresholds': self.thresholds.to_dict(),
         | 
| 260 | 
            -
                        'restart_policy': self.restart_policy.to_dict(),
         | 
| 261 | 
            -
                        'monitoring': self.monitoring.to_dict(),
         | 
| 262 | 
            -
                        'platform_overrides': self.platform_overrides.to_dict(),
         | 
| 263 | 
            -
                        'process_command': self.process_command,
         | 
| 264 | 
            -
                        'process_args': self.process_args,
         | 
| 265 | 
            -
                        'process_env': self.process_env,
         | 
| 266 | 
            -
                        'working_directory': self.working_directory,
         | 
| 267 | 
            -
                        'enabled': self.enabled,
         | 
| 268 | 
            -
                        'auto_start': self.auto_start,
         | 
| 269 | 
            -
                        'persist_state': self.persist_state,
         | 
| 270 | 
            -
                        'state_file': self.state_file
         | 
| 271 | 
            -
                    }
         | 
| 272 | 
            -
                
         | 
| 273 | 
            -
                def validate(self) -> List[str]:
         | 
| 274 | 
            -
                    """Validate configuration and return list of issues."""
         | 
| 275 | 
            -
                    issues = []
         | 
| 276 | 
            -
                    
         | 
| 277 | 
            -
                    # Validate thresholds are in correct order
         | 
| 278 | 
            -
                    if self.thresholds.warning >= self.thresholds.critical:
         | 
| 279 | 
            -
                        issues.append("Warning threshold must be less than critical threshold")
         | 
| 280 | 
            -
                    if self.thresholds.critical >= self.thresholds.emergency:
         | 
| 281 | 
            -
                        issues.append("Critical threshold must be less than emergency threshold")
         | 
| 282 | 
            -
                    
         | 
| 283 | 
            -
                    # Validate intervals
         | 
| 284 | 
            -
                    if self.monitoring.normal_interval <= 0:
         | 
| 285 | 
            -
                        issues.append("Normal monitoring interval must be positive")
         | 
| 286 | 
            -
                    if self.monitoring.warning_interval <= 0:
         | 
| 287 | 
            -
                        issues.append("Warning monitoring interval must be positive")
         | 
| 288 | 
            -
                    if self.monitoring.critical_interval <= 0:
         | 
| 289 | 
            -
                        issues.append("Critical monitoring interval must be positive")
         | 
| 290 | 
            -
                    
         | 
| 291 | 
            -
                    # Validate restart policy
         | 
| 292 | 
            -
                    if self.restart_policy.max_attempts < 0:
         | 
| 293 | 
            -
                        issues.append("Max restart attempts cannot be negative")
         | 
| 294 | 
            -
                    if self.restart_policy.initial_cooldown <= 0:
         | 
| 295 | 
            -
                        issues.append("Initial cooldown must be positive")
         | 
| 296 | 
            -
                    
         | 
| 297 | 
            -
                    # Validate process command
         | 
| 298 | 
            -
                    if not self.process_command:
         | 
| 299 | 
            -
                        issues.append("Process command cannot be empty")
         | 
| 300 | 
            -
                    
         | 
| 301 | 
            -
                    return issues
         | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
            def get_default_config() -> MemoryGuardianConfig:
         | 
| 305 | 
            -
                """Get default configuration adjusted for current platform."""
         | 
| 306 | 
            -
                config = MemoryGuardianConfig.for_platform()
         | 
| 307 | 
            -
                
         | 
| 308 | 
            -
                # Try to adjust for available system memory
         | 
| 309 | 
            -
                try:
         | 
| 310 | 
            -
                    import psutil
         | 
| 311 | 
            -
                    total_memory_mb = psutil.virtual_memory().total // (1024 * 1024)
         | 
| 312 | 
            -
                    config.thresholds.adjust_for_system_memory(total_memory_mb)
         | 
| 313 | 
            -
                except ImportError:
         | 
| 314 | 
            -
                    # psutil not available, use defaults
         | 
| 315 | 
            -
                    pass
         | 
| 316 | 
            -
                except Exception:
         | 
| 317 | 
            -
                    # Any other error, use defaults
         | 
| 318 | 
            -
                    pass
         | 
| 319 | 
            -
                
         | 
| 320 | 
            -
                # Override with environment variables
         | 
| 321 | 
            -
                env_config = MemoryGuardianConfig.from_env()
         | 
| 322 | 
            -
                if env_config.enabled != config.enabled:
         | 
| 323 | 
            -
                    config = env_config
         | 
| 324 | 
            -
                
         | 
| 325 | 
            -
                return config
         | 
| @@ -1,335 +0,0 @@ | |
| 1 | 
            -
            """YAML configuration support for Memory Guardian.
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            This module provides YAML configuration loading and validation for
         | 
| 4 | 
            -
            the Memory Guardian service, allowing users to configure memory monitoring
         | 
| 5 | 
            -
            through configuration files.
         | 
| 6 | 
            -
            """
         | 
| 7 | 
            -
             | 
| 8 | 
            -
            import os
         | 
| 9 | 
            -
            from pathlib import Path
         | 
| 10 | 
            -
            from typing import Optional, Dict, Any
         | 
| 11 | 
            -
             | 
| 12 | 
            -
            import yaml
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            from claude_mpm.config.memory_guardian_config import (
         | 
| 15 | 
            -
                MemoryGuardianConfig,
         | 
| 16 | 
            -
                MemoryThresholds,
         | 
| 17 | 
            -
                RestartPolicy,
         | 
| 18 | 
            -
                MonitoringConfig
         | 
| 19 | 
            -
            )
         | 
| 20 | 
            -
            from claude_mpm.core.logging_config import get_logger
         | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
            logger = get_logger(__name__)
         | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
            # Default configuration file locations
         | 
| 27 | 
            -
            DEFAULT_CONFIG_LOCATIONS = [
         | 
| 28 | 
            -
                Path.home() / ".claude-mpm" / "config" / "memory_guardian.yaml",
         | 
| 29 | 
            -
                Path.home() / ".claude-mpm" / "memory_guardian.yaml",
         | 
| 30 | 
            -
                Path.cwd() / ".claude-mpm" / "memory_guardian.yaml",
         | 
| 31 | 
            -
                Path.cwd() / "memory_guardian.yaml",
         | 
| 32 | 
            -
            ]
         | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
            def find_config_file() -> Optional[Path]:
         | 
| 36 | 
            -
                """Find memory guardian configuration file in standard locations.
         | 
| 37 | 
            -
                
         | 
| 38 | 
            -
                Returns:
         | 
| 39 | 
            -
                    Path to configuration file or None if not found
         | 
| 40 | 
            -
                """
         | 
| 41 | 
            -
                for path in DEFAULT_CONFIG_LOCATIONS:
         | 
| 42 | 
            -
                    if path.exists():
         | 
| 43 | 
            -
                        logger.debug(f"Found memory guardian config at: {path}")
         | 
| 44 | 
            -
                        return path
         | 
| 45 | 
            -
                
         | 
| 46 | 
            -
                return None
         | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
            def load_yaml_config(config_path: Path) -> Optional[Dict[str, Any]]:
         | 
| 50 | 
            -
                """Load YAML configuration from file.
         | 
| 51 | 
            -
                
         | 
| 52 | 
            -
                Args:
         | 
| 53 | 
            -
                    config_path: Path to YAML configuration file
         | 
| 54 | 
            -
                    
         | 
| 55 | 
            -
                Returns:
         | 
| 56 | 
            -
                    Dictionary of configuration data or None if loading failed
         | 
| 57 | 
            -
                """
         | 
| 58 | 
            -
                try:
         | 
| 59 | 
            -
                    if not config_path.exists():
         | 
| 60 | 
            -
                        logger.warning(f"Configuration file not found: {config_path}")
         | 
| 61 | 
            -
                        return None
         | 
| 62 | 
            -
                    
         | 
| 63 | 
            -
                    with open(config_path, 'r') as f:
         | 
| 64 | 
            -
                        config_data = yaml.safe_load(f)
         | 
| 65 | 
            -
                    
         | 
| 66 | 
            -
                    if not config_data:
         | 
| 67 | 
            -
                        logger.warning(f"Empty configuration file: {config_path}")
         | 
| 68 | 
            -
                        return {}
         | 
| 69 | 
            -
                    
         | 
| 70 | 
            -
                    logger.info(f"Loaded configuration from: {config_path}")
         | 
| 71 | 
            -
                    return config_data
         | 
| 72 | 
            -
                    
         | 
| 73 | 
            -
                except yaml.YAMLError as e:
         | 
| 74 | 
            -
                    logger.error(f"Invalid YAML in configuration file: {e}")
         | 
| 75 | 
            -
                    return None
         | 
| 76 | 
            -
                except Exception as e:
         | 
| 77 | 
            -
                    logger.error(f"Failed to load configuration file: {e}")
         | 
| 78 | 
            -
                    return None
         | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
            def create_config_from_yaml(yaml_data: Dict[str, Any]) -> MemoryGuardianConfig:
         | 
| 82 | 
            -
                """Create MemoryGuardianConfig from YAML data.
         | 
| 83 | 
            -
                
         | 
| 84 | 
            -
                Args:
         | 
| 85 | 
            -
                    yaml_data: Dictionary of configuration data from YAML
         | 
| 86 | 
            -
                    
         | 
| 87 | 
            -
                Returns:
         | 
| 88 | 
            -
                    MemoryGuardianConfig instance
         | 
| 89 | 
            -
                """
         | 
| 90 | 
            -
                config = MemoryGuardianConfig()
         | 
| 91 | 
            -
                
         | 
| 92 | 
            -
                # General settings
         | 
| 93 | 
            -
                config.enabled = yaml_data.get('enabled', config.enabled)
         | 
| 94 | 
            -
                config.auto_start = yaml_data.get('auto_start', config.auto_start)
         | 
| 95 | 
            -
                config.persist_state = yaml_data.get('persist_state', config.persist_state)
         | 
| 96 | 
            -
                config.state_file = yaml_data.get('state_file', config.state_file)
         | 
| 97 | 
            -
                
         | 
| 98 | 
            -
                # Memory thresholds
         | 
| 99 | 
            -
                if 'thresholds' in yaml_data:
         | 
| 100 | 
            -
                    thresholds = yaml_data['thresholds']
         | 
| 101 | 
            -
                    config.thresholds = MemoryThresholds(
         | 
| 102 | 
            -
                        warning=thresholds.get('warning', config.thresholds.warning),
         | 
| 103 | 
            -
                        critical=thresholds.get('critical', config.thresholds.critical),
         | 
| 104 | 
            -
                        emergency=thresholds.get('emergency', config.thresholds.emergency)
         | 
| 105 | 
            -
                    )
         | 
| 106 | 
            -
                
         | 
| 107 | 
            -
                # Monitoring configuration
         | 
| 108 | 
            -
                if 'monitoring' in yaml_data:
         | 
| 109 | 
            -
                    monitoring = yaml_data['monitoring']
         | 
| 110 | 
            -
                    config.monitoring = MonitoringConfig(
         | 
| 111 | 
            -
                        check_interval=monitoring.get('check_interval', config.monitoring.check_interval),
         | 
| 112 | 
            -
                        check_interval_warning=monitoring.get('check_interval_warning', config.monitoring.check_interval_warning),
         | 
| 113 | 
            -
                        check_interval_critical=monitoring.get('check_interval_critical', config.monitoring.check_interval_critical),
         | 
| 114 | 
            -
                        log_memory_stats=monitoring.get('log_memory_stats', config.monitoring.log_memory_stats),
         | 
| 115 | 
            -
                        log_interval=monitoring.get('log_interval', config.monitoring.log_interval)
         | 
| 116 | 
            -
                    )
         | 
| 117 | 
            -
                
         | 
| 118 | 
            -
                # Restart policy
         | 
| 119 | 
            -
                if 'restart_policy' in yaml_data:
         | 
| 120 | 
            -
                    policy = yaml_data['restart_policy']
         | 
| 121 | 
            -
                    config.restart_policy = RestartPolicy(
         | 
| 122 | 
            -
                        max_attempts=policy.get('max_attempts', config.restart_policy.max_attempts),
         | 
| 123 | 
            -
                        attempt_window=policy.get('attempt_window', config.restart_policy.attempt_window),
         | 
| 124 | 
            -
                        cooldown_base=policy.get('cooldown_base', config.restart_policy.cooldown_base),
         | 
| 125 | 
            -
                        cooldown_multiplier=policy.get('cooldown_multiplier', config.restart_policy.cooldown_multiplier),
         | 
| 126 | 
            -
                        cooldown_max=policy.get('cooldown_max', config.restart_policy.cooldown_max),
         | 
| 127 | 
            -
                        graceful_timeout=policy.get('graceful_timeout', config.restart_policy.graceful_timeout),
         | 
| 128 | 
            -
                        force_kill_timeout=policy.get('force_kill_timeout', config.restart_policy.force_kill_timeout)
         | 
| 129 | 
            -
                    )
         | 
| 130 | 
            -
                
         | 
| 131 | 
            -
                # Process configuration
         | 
| 132 | 
            -
                if 'process' in yaml_data:
         | 
| 133 | 
            -
                    process = yaml_data['process']
         | 
| 134 | 
            -
                    config.process_command = process.get('command', config.process_command)
         | 
| 135 | 
            -
                    config.process_args = process.get('args', config.process_args)
         | 
| 136 | 
            -
                    config.process_env = process.get('env', config.process_env)
         | 
| 137 | 
            -
                    config.working_directory = process.get('working_directory', config.working_directory)
         | 
| 138 | 
            -
                
         | 
| 139 | 
            -
                return config
         | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
            def load_config(config_path: Optional[Path] = None) -> Optional[MemoryGuardianConfig]:
         | 
| 143 | 
            -
                """Load memory guardian configuration from YAML file.
         | 
| 144 | 
            -
                
         | 
| 145 | 
            -
                Args:
         | 
| 146 | 
            -
                    config_path: Optional path to configuration file.
         | 
| 147 | 
            -
                                If not provided, searches standard locations.
         | 
| 148 | 
            -
                
         | 
| 149 | 
            -
                Returns:
         | 
| 150 | 
            -
                    MemoryGuardianConfig instance or None if loading failed
         | 
| 151 | 
            -
                """
         | 
| 152 | 
            -
                # Find configuration file if not specified
         | 
| 153 | 
            -
                if config_path is None:
         | 
| 154 | 
            -
                    config_path = find_config_file()
         | 
| 155 | 
            -
                    if config_path is None:
         | 
| 156 | 
            -
                        logger.debug("No memory guardian configuration file found")
         | 
| 157 | 
            -
                        return None
         | 
| 158 | 
            -
                
         | 
| 159 | 
            -
                # Load YAML data
         | 
| 160 | 
            -
                yaml_data = load_yaml_config(config_path)
         | 
| 161 | 
            -
                if yaml_data is None:
         | 
| 162 | 
            -
                    return None
         | 
| 163 | 
            -
                
         | 
| 164 | 
            -
                # Create configuration
         | 
| 165 | 
            -
                try:
         | 
| 166 | 
            -
                    config = create_config_from_yaml(yaml_data)
         | 
| 167 | 
            -
                    
         | 
| 168 | 
            -
                    # Validate configuration
         | 
| 169 | 
            -
                    issues = config.validate()
         | 
| 170 | 
            -
                    if issues:
         | 
| 171 | 
            -
                        for issue in issues:
         | 
| 172 | 
            -
                            logger.warning(f"Configuration validation issue: {issue}")
         | 
| 173 | 
            -
                    
         | 
| 174 | 
            -
                    return config
         | 
| 175 | 
            -
                    
         | 
| 176 | 
            -
                except Exception as e:
         | 
| 177 | 
            -
                    logger.error(f"Failed to create configuration from YAML: {e}")
         | 
| 178 | 
            -
                    return None
         | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
            def save_config(config: MemoryGuardianConfig, config_path: Optional[Path] = None) -> bool:
         | 
| 182 | 
            -
                """Save memory guardian configuration to YAML file.
         | 
| 183 | 
            -
                
         | 
| 184 | 
            -
                Args:
         | 
| 185 | 
            -
                    config: MemoryGuardianConfig instance to save
         | 
| 186 | 
            -
                    config_path: Optional path to save configuration.
         | 
| 187 | 
            -
                                If not provided, uses default location.
         | 
| 188 | 
            -
                
         | 
| 189 | 
            -
                Returns:
         | 
| 190 | 
            -
                    True if save successful, False otherwise
         | 
| 191 | 
            -
                """
         | 
| 192 | 
            -
                try:
         | 
| 193 | 
            -
                    # Determine save path
         | 
| 194 | 
            -
                    if config_path is None:
         | 
| 195 | 
            -
                        config_path = Path.home() / ".claude-mpm" / "config" / "memory_guardian.yaml"
         | 
| 196 | 
            -
                    
         | 
| 197 | 
            -
                    # Ensure directory exists
         | 
| 198 | 
            -
                    config_path.parent.mkdir(parents=True, exist_ok=True)
         | 
| 199 | 
            -
                    
         | 
| 200 | 
            -
                    # Convert configuration to dictionary
         | 
| 201 | 
            -
                    config_dict = config.to_dict()
         | 
| 202 | 
            -
                    
         | 
| 203 | 
            -
                    # Write to file
         | 
| 204 | 
            -
                    with open(config_path, 'w') as f:
         | 
| 205 | 
            -
                        yaml.dump(config_dict, f, default_flow_style=False, sort_keys=False)
         | 
| 206 | 
            -
                    
         | 
| 207 | 
            -
                    logger.info(f"Saved configuration to: {config_path}")
         | 
| 208 | 
            -
                    return True
         | 
| 209 | 
            -
                    
         | 
| 210 | 
            -
                except Exception as e:
         | 
| 211 | 
            -
                    logger.error(f"Failed to save configuration: {e}")
         | 
| 212 | 
            -
                    return False
         | 
| 213 | 
            -
             | 
| 214 | 
            -
             | 
| 215 | 
            -
            def create_default_config_file(config_path: Optional[Path] = None) -> bool:
         | 
| 216 | 
            -
                """Create a default memory guardian configuration file.
         | 
| 217 | 
            -
                
         | 
| 218 | 
            -
                Args:
         | 
| 219 | 
            -
                    config_path: Optional path for configuration file.
         | 
| 220 | 
            -
                                If not provided, uses default location.
         | 
| 221 | 
            -
                
         | 
| 222 | 
            -
                Returns:
         | 
| 223 | 
            -
                    True if file created successfully, False otherwise
         | 
| 224 | 
            -
                """
         | 
| 225 | 
            -
                try:
         | 
| 226 | 
            -
                    # Determine save path
         | 
| 227 | 
            -
                    if config_path is None:
         | 
| 228 | 
            -
                        config_path = Path.home() / ".claude-mpm" / "config" / "memory_guardian.yaml"
         | 
| 229 | 
            -
                    
         | 
| 230 | 
            -
                    # Check if file already exists
         | 
| 231 | 
            -
                    if config_path.exists():
         | 
| 232 | 
            -
                        logger.warning(f"Configuration file already exists: {config_path}")
         | 
| 233 | 
            -
                        return False
         | 
| 234 | 
            -
                    
         | 
| 235 | 
            -
                    # Create default configuration
         | 
| 236 | 
            -
                    config = MemoryGuardianConfig()
         | 
| 237 | 
            -
                    
         | 
| 238 | 
            -
                    # Add helpful comments to YAML
         | 
| 239 | 
            -
                    yaml_content = """# Memory Guardian Configuration
         | 
| 240 | 
            -
            # This file configures memory monitoring and automatic restart for Claude Code
         | 
| 241 | 
            -
             | 
| 242 | 
            -
            # Enable/disable memory monitoring
         | 
| 243 | 
            -
            enabled: true
         | 
| 244 | 
            -
             | 
| 245 | 
            -
            # Automatically start monitoring when service initializes
         | 
| 246 | 
            -
            auto_start: true
         | 
| 247 | 
            -
             | 
| 248 | 
            -
            # Preserve state across restarts
         | 
| 249 | 
            -
            persist_state: true
         | 
| 250 | 
            -
             | 
| 251 | 
            -
            # Path to state file for persistence
         | 
| 252 | 
            -
            state_file: ~/.claude-mpm/state/memory_guardian.json
         | 
| 253 | 
            -
             | 
| 254 | 
            -
            # Memory thresholds in MB
         | 
| 255 | 
            -
            thresholds:
         | 
| 256 | 
            -
              # Warning threshold - logs warnings
         | 
| 257 | 
            -
              warning: 14400  # 14GB
         | 
| 258 | 
            -
              
         | 
| 259 | 
            -
              # Critical threshold - triggers restart
         | 
| 260 | 
            -
              critical: 18000  # 18GB
         | 
| 261 | 
            -
              
         | 
| 262 | 
            -
              # Emergency threshold - immediate restart
         | 
| 263 | 
            -
              emergency: 21600  # 21GB
         | 
| 264 | 
            -
             | 
| 265 | 
            -
            # Monitoring configuration
         | 
| 266 | 
            -
            monitoring:
         | 
| 267 | 
            -
              # Default check interval in seconds
         | 
| 268 | 
            -
              check_interval: 30
         | 
| 269 | 
            -
              
         | 
| 270 | 
            -
              # Check interval when in warning state
         | 
| 271 | 
            -
              check_interval_warning: 15
         | 
| 272 | 
            -
              
         | 
| 273 | 
            -
              # Check interval when in critical state
         | 
| 274 | 
            -
              check_interval_critical: 5
         | 
| 275 | 
            -
              
         | 
| 276 | 
            -
              # Enable periodic memory statistics logging
         | 
| 277 | 
            -
              log_memory_stats: true
         | 
| 278 | 
            -
              
         | 
| 279 | 
            -
              # Statistics logging interval in seconds
         | 
| 280 | 
            -
              log_interval: 60
         | 
| 281 | 
            -
             | 
| 282 | 
            -
            # Restart policy configuration
         | 
| 283 | 
            -
            restart_policy:
         | 
| 284 | 
            -
              # Maximum restart attempts (0 = unlimited)
         | 
| 285 | 
            -
              max_attempts: 3
         | 
| 286 | 
            -
              
         | 
| 287 | 
            -
              # Time window for counting attempts (seconds)
         | 
| 288 | 
            -
              attempt_window: 3600  # 1 hour
         | 
| 289 | 
            -
              
         | 
| 290 | 
            -
              # Base cooldown between restarts (seconds)
         | 
| 291 | 
            -
              cooldown_base: 10
         | 
| 292 | 
            -
              
         | 
| 293 | 
            -
              # Cooldown multiplier for consecutive failures
         | 
| 294 | 
            -
              cooldown_multiplier: 2.0
         | 
| 295 | 
            -
              
         | 
| 296 | 
            -
              # Maximum cooldown period (seconds)
         | 
| 297 | 
            -
              cooldown_max: 300  # 5 minutes
         | 
| 298 | 
            -
              
         | 
| 299 | 
            -
              # Timeout for graceful shutdown (seconds)
         | 
| 300 | 
            -
              graceful_timeout: 30
         | 
| 301 | 
            -
              
         | 
| 302 | 
            -
              # Timeout for force kill if graceful fails (seconds)
         | 
| 303 | 
            -
              force_kill_timeout: 10
         | 
| 304 | 
            -
             | 
| 305 | 
            -
            # Process configuration (usually set by runner)
         | 
| 306 | 
            -
            process:
         | 
| 307 | 
            -
              # Command to execute (set by runner)
         | 
| 308 | 
            -
              command: ["claude"]
         | 
| 309 | 
            -
              
         | 
| 310 | 
            -
              # Additional arguments
         | 
| 311 | 
            -
              args: []
         | 
| 312 | 
            -
              
         | 
| 313 | 
            -
              # Environment variables
         | 
| 314 | 
            -
              env: {}
         | 
| 315 | 
            -
              
         | 
| 316 | 
            -
              # Working directory (defaults to current)
         | 
| 317 | 
            -
              working_directory: null
         | 
| 318 | 
            -
            """
         | 
| 319 | 
            -
                    
         | 
| 320 | 
            -
                    # Ensure directory exists
         | 
| 321 | 
            -
                    config_path.parent.mkdir(parents=True, exist_ok=True)
         | 
| 322 | 
            -
                    
         | 
| 323 | 
            -
                    # Write configuration file
         | 
| 324 | 
            -
                    with open(config_path, 'w') as f:
         | 
| 325 | 
            -
                        f.write(yaml_content)
         | 
| 326 | 
            -
                    
         | 
| 327 | 
            -
                    logger.info(f"Created default configuration file: {config_path}")
         | 
| 328 | 
            -
                    print(f"✓ Created memory guardian configuration at: {config_path}")
         | 
| 329 | 
            -
                    print("  Edit this file to customize memory thresholds and policies")
         | 
| 330 | 
            -
                    
         | 
| 331 | 
            -
                    return True
         | 
| 332 | 
            -
                    
         | 
| 333 | 
            -
                except Exception as e:
         | 
| 334 | 
            -
                    logger.error(f"Failed to create default configuration file: {e}")
         | 
| 335 | 
            -
                    return False
         |