claude-mpm 3.9.11__py3-none-any.whl → 4.0.3__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 +1 -1
- 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 +203 -81
- 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 +305 -197
- 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 +104 -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/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 +74 -70
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
- 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 +120 -54
- 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 +223 -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 +145 -65
- 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 +170 -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.3.dist-info}/METADATA +27 -1
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.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.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            from pathlib import Path
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            """
         | 
| 2 4 | 
             
            Dependency caching system for smart dependency checking.
         | 
| 3 5 |  | 
| @@ -5,12 +7,10 @@ This module provides caching for dependency check results to avoid | |
| 5 7 | 
             
            redundant checks and improve startup performance.
         | 
| 6 8 | 
             
            """
         | 
| 7 9 |  | 
| 10 | 
            +
            import hashlib
         | 
| 8 11 | 
             
            import json
         | 
| 9 12 | 
             
            import time
         | 
| 10 | 
            -
            from pathlib import Path
         | 
| 11 13 | 
             
            from typing import Dict, Optional, Tuple
         | 
| 12 | 
            -
            import hashlib
         | 
| 13 | 
            -
            import logging
         | 
| 14 14 |  | 
| 15 15 | 
             
            from ..core.logger import get_logger
         | 
| 16 16 |  | 
| @@ -20,157 +20,154 @@ logger = get_logger(__name__) | |
| 20 20 | 
             
            class DependencyCache:
         | 
| 21 21 | 
             
                """
         | 
| 22 22 | 
             
                Manages caching of dependency check results.
         | 
| 23 | 
            -
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
                WHY: Dependency checking can be slow, especially when checking many packages.
         | 
| 25 25 | 
             
                By caching results keyed by deployment hash, we can skip checks when nothing
         | 
| 26 26 | 
             
                has changed, significantly improving startup time.
         | 
| 27 | 
            -
             | 
| 27 | 
            +
             | 
| 28 28 | 
             
                DESIGN DECISION: We use a file-based cache in .claude/agents/.dependency_cache
         | 
| 29 29 | 
             
                - Simple JSON format for easy debugging
         | 
| 30 30 | 
             
                - TTL-based expiration (24 hours default)
         | 
| 31 31 | 
             
                - Automatic invalidation when agent deployment changes
         | 
| 32 32 | 
             
                """
         | 
| 33 | 
            -
             | 
| 33 | 
            +
             | 
| 34 34 | 
             
                DEFAULT_TTL_SECONDS = 86400  # 24 hours
         | 
| 35 | 
            -
             | 
| 36 | 
            -
                def __init__( | 
| 35 | 
            +
             | 
| 36 | 
            +
                def __init__(
         | 
| 37 | 
            +
                    self, cache_dir: Optional[Path] = None, ttl_seconds: int = DEFAULT_TTL_SECONDS
         | 
| 38 | 
            +
                ):
         | 
| 37 39 | 
             
                    """
         | 
| 38 40 | 
             
                    Initialize the dependency cache.
         | 
| 39 | 
            -
             | 
| 41 | 
            +
             | 
| 40 42 | 
             
                    Args:
         | 
| 41 43 | 
             
                        cache_dir: Directory for cache files (default: .claude/agents/)
         | 
| 42 44 | 
             
                        ttl_seconds: Time-to-live for cache entries in seconds
         | 
| 43 45 | 
             
                    """
         | 
| 44 46 | 
             
                    if cache_dir is None:
         | 
| 45 47 | 
             
                        cache_dir = Path.cwd() / ".claude" / "agents"
         | 
| 46 | 
            -
             | 
| 48 | 
            +
             | 
| 47 49 | 
             
                    self.cache_dir = cache_dir
         | 
| 48 50 | 
             
                    self.cache_file = self.cache_dir / ".dependency_cache"
         | 
| 49 51 | 
             
                    self.ttl_seconds = ttl_seconds
         | 
| 50 52 | 
             
                    self._cache_data: Optional[Dict] = None
         | 
| 51 | 
            -
             | 
| 53 | 
            +
             | 
| 52 54 | 
             
                def _load_cache(self) -> Dict:
         | 
| 53 55 | 
             
                    """
         | 
| 54 56 | 
             
                    Load cache data from disk.
         | 
| 55 | 
            -
             | 
| 57 | 
            +
             | 
| 56 58 | 
             
                    Returns:
         | 
| 57 59 | 
             
                        Cache data dictionary or empty dict if not found.
         | 
| 58 60 | 
             
                    """
         | 
| 59 61 | 
             
                    if self._cache_data is not None:
         | 
| 60 62 | 
             
                        return self._cache_data
         | 
| 61 | 
            -
             | 
| 63 | 
            +
             | 
| 62 64 | 
             
                    if not self.cache_file.exists():
         | 
| 63 65 | 
             
                        self._cache_data = {}
         | 
| 64 66 | 
             
                        return self._cache_data
         | 
| 65 | 
            -
             | 
| 67 | 
            +
             | 
| 66 68 | 
             
                    try:
         | 
| 67 | 
            -
                        with open(self.cache_file,  | 
| 69 | 
            +
                        with open(self.cache_file, "r") as f:
         | 
| 68 70 | 
             
                            self._cache_data = json.load(f)
         | 
| 69 71 | 
             
                            return self._cache_data
         | 
| 70 72 | 
             
                    except Exception as e:
         | 
| 71 73 | 
             
                        logger.debug(f"Could not load dependency cache: {e}")
         | 
| 72 74 | 
             
                        self._cache_data = {}
         | 
| 73 75 | 
             
                        return self._cache_data
         | 
| 74 | 
            -
             | 
| 76 | 
            +
             | 
| 75 77 | 
             
                def _save_cache(self, cache_data: Dict) -> None:
         | 
| 76 78 | 
             
                    """
         | 
| 77 79 | 
             
                    Save cache data to disk.
         | 
| 78 | 
            -
             | 
| 80 | 
            +
             | 
| 79 81 | 
             
                    Args:
         | 
| 80 82 | 
             
                        cache_data: Cache data to save.
         | 
| 81 83 | 
             
                    """
         | 
| 82 84 | 
             
                    try:
         | 
| 83 85 | 
             
                        # Ensure directory exists
         | 
| 84 86 | 
             
                        self.cache_dir.mkdir(parents=True, exist_ok=True)
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                        with open(self.cache_file,  | 
| 87 | 
            +
             | 
| 88 | 
            +
                        with open(self.cache_file, "w") as f:
         | 
| 87 89 | 
             
                            json.dump(cache_data, f, indent=2)
         | 
| 88 | 
            -
             | 
| 90 | 
            +
             | 
| 89 91 | 
             
                        self._cache_data = cache_data
         | 
| 90 92 | 
             
                    except Exception as e:
         | 
| 91 93 | 
             
                        logger.debug(f"Could not save dependency cache: {e}")
         | 
| 92 | 
            -
             | 
| 94 | 
            +
             | 
| 93 95 | 
             
                def _generate_cache_key(self, deployment_hash: str, context: Dict) -> str:
         | 
| 94 96 | 
             
                    """
         | 
| 95 97 | 
             
                    Generate a cache key for dependency results.
         | 
| 96 | 
            -
             | 
| 98 | 
            +
             | 
| 97 99 | 
             
                    Args:
         | 
| 98 100 | 
             
                        deployment_hash: Hash of the current agent deployment
         | 
| 99 101 | 
             
                        context: Additional context (e.g., Python version, platform)
         | 
| 100 | 
            -
             | 
| 102 | 
            +
             | 
| 101 103 | 
             
                    Returns:
         | 
| 102 104 | 
             
                        Cache key string.
         | 
| 103 | 
            -
             | 
| 105 | 
            +
             | 
| 104 106 | 
             
                    WHY: We include context like Python version because dependency
         | 
| 105 107 | 
             
                    availability can vary between Python versions.
         | 
| 106 108 | 
             
                    """
         | 
| 107 109 | 
             
                    # Include important context in the cache key
         | 
| 108 | 
            -
                    import sys
         | 
| 109 110 | 
             
                    import platform
         | 
| 110 | 
            -
                    
         | 
| 111 | 
            +
                    import sys
         | 
| 112 | 
            +
             | 
| 111 113 | 
             
                    key_parts = [
         | 
| 112 114 | 
             
                        deployment_hash,
         | 
| 113 115 | 
             
                        f"py{sys.version_info.major}.{sys.version_info.minor}",
         | 
| 114 116 | 
             
                        platform.system().lower(),
         | 
| 115 | 
            -
                        platform.machine().lower()
         | 
| 117 | 
            +
                        platform.machine().lower(),
         | 
| 116 118 | 
             
                    ]
         | 
| 117 | 
            -
             | 
| 119 | 
            +
             | 
| 118 120 | 
             
                    # Add any additional context
         | 
| 119 121 | 
             
                    for key, value in sorted(context.items()):
         | 
| 120 122 | 
             
                        key_parts.append(f"{key}:{value}")
         | 
| 121 | 
            -
             | 
| 123 | 
            +
             | 
| 122 124 | 
             
                    # Create a hash of all parts for a compact key
         | 
| 123 125 | 
             
                    key_string = "|".join(key_parts)
         | 
| 124 126 | 
             
                    return hashlib.md5(key_string.encode()).hexdigest()
         | 
| 125 | 
            -
             | 
| 127 | 
            +
             | 
| 126 128 | 
             
                def get(
         | 
| 127 | 
            -
                    self,
         | 
| 128 | 
            -
                    deployment_hash: str,
         | 
| 129 | 
            -
                    context: Optional[Dict] = None
         | 
| 129 | 
            +
                    self, deployment_hash: str, context: Optional[Dict] = None
         | 
| 130 130 | 
             
                ) -> Optional[Dict]:
         | 
| 131 131 | 
             
                    """
         | 
| 132 132 | 
             
                    Get cached dependency check results.
         | 
| 133 | 
            -
             | 
| 133 | 
            +
             | 
| 134 134 | 
             
                    Args:
         | 
| 135 135 | 
             
                        deployment_hash: Hash of the current agent deployment
         | 
| 136 136 | 
             
                        context: Additional context for cache key
         | 
| 137 | 
            -
             | 
| 137 | 
            +
             | 
| 138 138 | 
             
                    Returns:
         | 
| 139 139 | 
             
                        Cached results or None if not found/expired.
         | 
| 140 140 | 
             
                    """
         | 
| 141 141 | 
             
                    if context is None:
         | 
| 142 142 | 
             
                        context = {}
         | 
| 143 | 
            -
             | 
| 143 | 
            +
             | 
| 144 144 | 
             
                    cache_data = self._load_cache()
         | 
| 145 145 | 
             
                    cache_key = self._generate_cache_key(deployment_hash, context)
         | 
| 146 | 
            -
             | 
| 146 | 
            +
             | 
| 147 147 | 
             
                    if cache_key not in cache_data:
         | 
| 148 148 | 
             
                        logger.debug(f"Cache miss for key {cache_key}")
         | 
| 149 149 | 
             
                        return None
         | 
| 150 | 
            -
             | 
| 150 | 
            +
             | 
| 151 151 | 
             
                    entry = cache_data[cache_key]
         | 
| 152 | 
            -
             | 
| 152 | 
            +
             | 
| 153 153 | 
             
                    # Check if entry has expired
         | 
| 154 154 | 
             
                    current_time = time.time()
         | 
| 155 | 
            -
                    if current_time - entry.get( | 
| 155 | 
            +
                    if current_time - entry.get("timestamp", 0) > self.ttl_seconds:
         | 
| 156 156 | 
             
                        logger.debug(f"Cache entry expired for key {cache_key}")
         | 
| 157 157 | 
             
                        # Remove expired entry
         | 
| 158 158 | 
             
                        del cache_data[cache_key]
         | 
| 159 159 | 
             
                        self._save_cache(cache_data)
         | 
| 160 160 | 
             
                        return None
         | 
| 161 | 
            -
             | 
| 161 | 
            +
             | 
| 162 162 | 
             
                    logger.debug(f"Cache hit for key {cache_key}")
         | 
| 163 | 
            -
                    return entry.get( | 
| 164 | 
            -
             | 
| 163 | 
            +
                    return entry.get("results")
         | 
| 164 | 
            +
             | 
| 165 165 | 
             
                def set(
         | 
| 166 | 
            -
                    self,
         | 
| 167 | 
            -
                    deployment_hash: str,
         | 
| 168 | 
            -
                    results: Dict,
         | 
| 169 | 
            -
                    context: Optional[Dict] = None
         | 
| 166 | 
            +
                    self, deployment_hash: str, results: Dict, context: Optional[Dict] = None
         | 
| 170 167 | 
             
                ) -> None:
         | 
| 171 168 | 
             
                    """
         | 
| 172 169 | 
             
                    Cache dependency check results.
         | 
| 173 | 
            -
             | 
| 170 | 
            +
             | 
| 174 171 | 
             
                    Args:
         | 
| 175 172 | 
             
                        deployment_hash: Hash of the current agent deployment
         | 
| 176 173 | 
             
                        results: Dependency check results to cache
         | 
| @@ -178,28 +175,28 @@ class DependencyCache: | |
| 178 175 | 
             
                    """
         | 
| 179 176 | 
             
                    if context is None:
         | 
| 180 177 | 
             
                        context = {}
         | 
| 181 | 
            -
             | 
| 178 | 
            +
             | 
| 182 179 | 
             
                    cache_data = self._load_cache()
         | 
| 183 180 | 
             
                    cache_key = self._generate_cache_key(deployment_hash, context)
         | 
| 184 | 
            -
             | 
| 181 | 
            +
             | 
| 185 182 | 
             
                    # Store with timestamp
         | 
| 186 183 | 
             
                    cache_data[cache_key] = {
         | 
| 187 | 
            -
                         | 
| 188 | 
            -
                         | 
| 189 | 
            -
                         | 
| 190 | 
            -
                         | 
| 184 | 
            +
                        "timestamp": time.time(),
         | 
| 185 | 
            +
                        "results": results,
         | 
| 186 | 
            +
                        "deployment_hash": deployment_hash,
         | 
| 187 | 
            +
                        "context": context,
         | 
| 191 188 | 
             
                    }
         | 
| 192 | 
            -
             | 
| 189 | 
            +
             | 
| 193 190 | 
             
                    # Clean up old entries while we're at it
         | 
| 194 191 | 
             
                    self._cleanup_expired_entries(cache_data)
         | 
| 195 | 
            -
             | 
| 192 | 
            +
             | 
| 196 193 | 
             
                    self._save_cache(cache_data)
         | 
| 197 194 | 
             
                    logger.debug(f"Cached results for key {cache_key}")
         | 
| 198 | 
            -
             | 
| 195 | 
            +
             | 
| 199 196 | 
             
                def invalidate(self, deployment_hash: Optional[str] = None) -> None:
         | 
| 200 197 | 
             
                    """
         | 
| 201 198 | 
             
                    Invalidate cache entries.
         | 
| 202 | 
            -
             | 
| 199 | 
            +
             | 
| 203 200 | 
             
                    Args:
         | 
| 204 201 | 
             
                        deployment_hash: If provided, only invalidate entries for this hash.
         | 
| 205 202 | 
             
                                       If None, invalidate all entries.
         | 
| @@ -213,69 +210,71 @@ class DependencyCache: | |
| 213 210 | 
             
                        # Clear entries for specific deployment
         | 
| 214 211 | 
             
                        cache_data = self._load_cache()
         | 
| 215 212 | 
             
                        keys_to_remove = []
         | 
| 216 | 
            -
             | 
| 213 | 
            +
             | 
| 217 214 | 
             
                        for key, entry in cache_data.items():
         | 
| 218 | 
            -
                            if entry.get( | 
| 215 | 
            +
                            if entry.get("deployment_hash") == deployment_hash:
         | 
| 219 216 | 
             
                                keys_to_remove.append(key)
         | 
| 220 | 
            -
             | 
| 217 | 
            +
             | 
| 221 218 | 
             
                        for key in keys_to_remove:
         | 
| 222 219 | 
             
                            del cache_data[key]
         | 
| 223 | 
            -
             | 
| 220 | 
            +
             | 
| 224 221 | 
             
                        if keys_to_remove:
         | 
| 225 222 | 
             
                            self._save_cache(cache_data)
         | 
| 226 | 
            -
                            logger.info( | 
| 227 | 
            -
             | 
| 223 | 
            +
                            logger.info(
         | 
| 224 | 
            +
                                f"Invalidated {len(keys_to_remove)} cache entries for deployment {deployment_hash[:8]}..."
         | 
| 225 | 
            +
                            )
         | 
| 226 | 
            +
             | 
| 228 227 | 
             
                def _cleanup_expired_entries(self, cache_data: Dict) -> None:
         | 
| 229 228 | 
             
                    """
         | 
| 230 229 | 
             
                    Remove expired entries from cache data.
         | 
| 231 | 
            -
             | 
| 230 | 
            +
             | 
| 232 231 | 
             
                    Args:
         | 
| 233 232 | 
             
                        cache_data: Cache data dictionary to clean.
         | 
| 234 | 
            -
             | 
| 233 | 
            +
             | 
| 235 234 | 
             
                    WHY: We clean up expired entries periodically to prevent the cache
         | 
| 236 235 | 
             
                    from growing indefinitely.
         | 
| 237 236 | 
             
                    """
         | 
| 238 237 | 
             
                    current_time = time.time()
         | 
| 239 238 | 
             
                    keys_to_remove = []
         | 
| 240 | 
            -
             | 
| 239 | 
            +
             | 
| 241 240 | 
             
                    for key, entry in cache_data.items():
         | 
| 242 | 
            -
                        if current_time - entry.get( | 
| 241 | 
            +
                        if current_time - entry.get("timestamp", 0) > self.ttl_seconds:
         | 
| 243 242 | 
             
                            keys_to_remove.append(key)
         | 
| 244 | 
            -
             | 
| 243 | 
            +
             | 
| 245 244 | 
             
                    for key in keys_to_remove:
         | 
| 246 245 | 
             
                        del cache_data[key]
         | 
| 247 | 
            -
             | 
| 246 | 
            +
             | 
| 248 247 | 
             
                    if keys_to_remove:
         | 
| 249 248 | 
             
                        logger.debug(f"Cleaned up {len(keys_to_remove)} expired cache entries")
         | 
| 250 | 
            -
             | 
| 249 | 
            +
             | 
| 251 250 | 
             
                def get_cache_stats(self) -> Dict:
         | 
| 252 251 | 
             
                    """
         | 
| 253 252 | 
             
                    Get statistics about the cache.
         | 
| 254 | 
            -
             | 
| 253 | 
            +
             | 
| 255 254 | 
             
                    Returns:
         | 
| 256 255 | 
             
                        Dictionary with cache statistics.
         | 
| 257 256 | 
             
                    """
         | 
| 258 257 | 
             
                    cache_data = self._load_cache()
         | 
| 259 258 | 
             
                    current_time = time.time()
         | 
| 260 | 
            -
             | 
| 259 | 
            +
             | 
| 261 260 | 
             
                    total_entries = len(cache_data)
         | 
| 262 261 | 
             
                    expired_entries = 0
         | 
| 263 262 | 
             
                    valid_entries = 0
         | 
| 264 | 
            -
             | 
| 263 | 
            +
             | 
| 265 264 | 
             
                    for entry in cache_data.values():
         | 
| 266 | 
            -
                        if current_time - entry.get( | 
| 265 | 
            +
                        if current_time - entry.get("timestamp", 0) > self.ttl_seconds:
         | 
| 267 266 | 
             
                            expired_entries += 1
         | 
| 268 267 | 
             
                        else:
         | 
| 269 268 | 
             
                            valid_entries += 1
         | 
| 270 | 
            -
             | 
| 269 | 
            +
             | 
| 271 270 | 
             
                    return {
         | 
| 272 | 
            -
                         | 
| 273 | 
            -
                         | 
| 274 | 
            -
                         | 
| 275 | 
            -
                         | 
| 276 | 
            -
                         | 
| 271 | 
            +
                        "total_entries": total_entries,
         | 
| 272 | 
            +
                        "valid_entries": valid_entries,
         | 
| 273 | 
            +
                        "expired_entries": expired_entries,
         | 
| 274 | 
            +
                        "cache_file": str(self.cache_file),
         | 
| 275 | 
            +
                        "ttl_seconds": self.ttl_seconds,
         | 
| 277 276 | 
             
                    }
         | 
| 278 | 
            -
             | 
| 277 | 
            +
             | 
| 279 278 | 
             
                def clear(self) -> None:
         | 
| 280 279 | 
             
                    """
         | 
| 281 280 | 
             
                    Clear all cache entries.
         | 
| @@ -286,91 +285,87 @@ class DependencyCache: | |
| 286 285 | 
             
            class SmartDependencyChecker:
         | 
| 287 286 | 
             
                """
         | 
| 288 287 | 
             
                Combines caching with agent dependency checking for smart, efficient checks.
         | 
| 289 | 
            -
             | 
| 288 | 
            +
             | 
| 290 289 | 
             
                WHY: This class orchestrates the smart dependency checking by combining:
         | 
| 291 290 | 
             
                - Change detection (only check when agents change)
         | 
| 292 291 | 
             
                - Caching (reuse results when nothing has changed)
         | 
| 293 292 | 
             
                - Environment awareness (only prompt in appropriate contexts)
         | 
| 294 293 | 
             
                """
         | 
| 295 | 
            -
             | 
| 294 | 
            +
             | 
| 296 295 | 
             
                def __init__(self, cache_ttl_seconds: int = DependencyCache.DEFAULT_TTL_SECONDS):
         | 
| 297 296 | 
             
                    """
         | 
| 298 297 | 
             
                    Initialize the smart dependency checker.
         | 
| 299 | 
            -
             | 
| 298 | 
            +
             | 
| 300 299 | 
             
                    Args:
         | 
| 301 300 | 
             
                        cache_ttl_seconds: TTL for cache entries.
         | 
| 302 301 | 
             
                    """
         | 
| 303 302 | 
             
                    self.cache = DependencyCache(ttl_seconds=cache_ttl_seconds)
         | 
| 304 303 | 
             
                    self._last_check_time = 0
         | 
| 305 304 | 
             
                    self._min_check_interval = 60  # Don't check more than once per minute
         | 
| 306 | 
            -
             | 
| 305 | 
            +
             | 
| 307 306 | 
             
                def should_check_dependencies(
         | 
| 308 | 
            -
                    self,
         | 
| 309 | 
            -
                    force_check: bool = False,
         | 
| 310 | 
            -
                    deployment_hash: Optional[str] = None
         | 
| 307 | 
            +
                    self, force_check: bool = False, deployment_hash: Optional[str] = None
         | 
| 311 308 | 
             
                ) -> Tuple[bool, str]:
         | 
| 312 309 | 
             
                    """
         | 
| 313 310 | 
             
                    Determine if dependency checking should be performed.
         | 
| 314 | 
            -
             | 
| 311 | 
            +
             | 
| 315 312 | 
             
                    Args:
         | 
| 316 313 | 
             
                        force_check: Force checking regardless of cache/changes
         | 
| 317 314 | 
             
                        deployment_hash: Current deployment hash
         | 
| 318 | 
            -
             | 
| 315 | 
            +
             | 
| 319 316 | 
             
                    Returns:
         | 
| 320 317 | 
             
                        Tuple of (should_check, reason)
         | 
| 321 318 | 
             
                    """
         | 
| 322 319 | 
             
                    if force_check:
         | 
| 323 320 | 
             
                        return True, "Forced check requested"
         | 
| 324 | 
            -
             | 
| 321 | 
            +
             | 
| 325 322 | 
             
                    # Rate limiting - don't check too frequently
         | 
| 326 323 | 
             
                    current_time = time.time()
         | 
| 327 324 | 
             
                    if current_time - self._last_check_time < self._min_check_interval:
         | 
| 328 325 | 
             
                        return False, f"Checked recently (within {self._min_check_interval}s)"
         | 
| 329 | 
            -
             | 
| 326 | 
            +
             | 
| 330 327 | 
             
                    # Check if we have valid cached results
         | 
| 331 328 | 
             
                    if deployment_hash:
         | 
| 332 329 | 
             
                        cached_results = self.cache.get(deployment_hash)
         | 
| 333 330 | 
             
                        if cached_results:
         | 
| 334 331 | 
             
                            return False, "Valid cached results available"
         | 
| 335 | 
            -
             | 
| 332 | 
            +
             | 
| 336 333 | 
             
                    return True, "No valid cache, checking needed"
         | 
| 337 | 
            -
             | 
| 334 | 
            +
             | 
| 338 335 | 
             
                def get_or_check_dependencies(
         | 
| 339 | 
            -
                    self,
         | 
| 340 | 
            -
                    loader,  # AgentDependencyLoader instance
         | 
| 341 | 
            -
                    force_check: bool = False
         | 
| 336 | 
            +
                    self, loader, force_check: bool = False  # AgentDependencyLoader instance
         | 
| 342 337 | 
             
                ) -> Tuple[Dict, bool]:
         | 
| 343 338 | 
             
                    """
         | 
| 344 339 | 
             
                    Get dependency results from cache or perform check.
         | 
| 345 | 
            -
             | 
| 340 | 
            +
             | 
| 346 341 | 
             
                    Args:
         | 
| 347 342 | 
             
                        loader: AgentDependencyLoader instance
         | 
| 348 343 | 
             
                        force_check: Force checking even if cached
         | 
| 349 | 
            -
             | 
| 344 | 
            +
             | 
| 350 345 | 
             
                    Returns:
         | 
| 351 346 | 
             
                        Tuple of (results, was_cached)
         | 
| 352 347 | 
             
                    """
         | 
| 353 348 | 
             
                    # Check if agents have changed
         | 
| 354 349 | 
             
                    has_changed, deployment_hash = loader.has_agents_changed()
         | 
| 355 | 
            -
             | 
| 350 | 
            +
             | 
| 356 351 | 
             
                    # Try to get cached results first
         | 
| 357 352 | 
             
                    if not force_check and not has_changed:
         | 
| 358 353 | 
             
                        cached_results = self.cache.get(deployment_hash)
         | 
| 359 354 | 
             
                        if cached_results:
         | 
| 360 355 | 
             
                            logger.info("Using cached dependency check results")
         | 
| 361 356 | 
             
                            return cached_results, True
         | 
| 362 | 
            -
             | 
| 357 | 
            +
             | 
| 363 358 | 
             
                    # Perform actual dependency check
         | 
| 364 359 | 
             
                    logger.info("Performing dependency check...")
         | 
| 365 360 | 
             
                    results = loader.load_and_check()
         | 
| 366 | 
            -
             | 
| 361 | 
            +
             | 
| 367 362 | 
             
                    # Cache the results
         | 
| 368 363 | 
             
                    self.cache.set(deployment_hash, results)
         | 
| 369 | 
            -
             | 
| 364 | 
            +
             | 
| 370 365 | 
             
                    # Mark deployment as checked
         | 
| 371 366 | 
             
                    loader.mark_deployment_checked(deployment_hash, results)
         | 
| 372 | 
            -
             | 
| 367 | 
            +
             | 
| 373 368 | 
             
                    # Update last check time
         | 
| 374 369 | 
             
                    self._last_check_time = time.time()
         | 
| 375 | 
            -
             | 
| 376 | 
            -
                    return results, False
         | 
| 370 | 
            +
             | 
| 371 | 
            +
                    return results, False
         |