claude-mpm 3.9.9__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 +155 -0
- 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 +90 -49
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +21 -18
- 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 +143 -762
- 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 -1150
- 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 +217 -0
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +36 -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 +571 -0
- 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 +40 -23
- 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 +14 -21
- 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 +97 -93
- claude_mpm/services/mcp_gateway/main.py +307 -127
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
- claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
- 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 +110 -121
- 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 +20 -534
- 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 +9 -0
- claude_mpm/storage/state_storage.py +552 -0
- 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.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/core/config_paths.py +0 -150
- 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/memory_guardian.py +0 -770
- claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
- 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.9.dist-info/RECORD +0 -293
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
    
        claude_mpm/core/container.py
    CHANGED
    
    | @@ -17,24 +17,26 @@ from abc import ABC | |
| 17 17 | 
             
            from enum import Enum
         | 
| 18 18 | 
             
            from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar, Union
         | 
| 19 19 |  | 
| 20 | 
            -
            from .logger import get_logger
         | 
| 21 20 | 
             
            from claude_mpm.services.core.interfaces import IServiceContainer
         | 
| 22 21 |  | 
| 22 | 
            +
            from .logger import get_logger
         | 
| 23 | 
            +
             | 
| 23 24 | 
             
            logger = get_logger(__name__)
         | 
| 24 25 |  | 
| 25 | 
            -
            T = TypeVar( | 
| 26 | 
            +
            T = TypeVar("T")
         | 
| 26 27 |  | 
| 27 28 |  | 
| 28 29 | 
             
            class ServiceLifetime(Enum):
         | 
| 29 30 | 
             
                """Service lifetime options."""
         | 
| 31 | 
            +
             | 
| 30 32 | 
             
                SINGLETON = "singleton"  # One instance per container
         | 
| 31 33 | 
             
                TRANSIENT = "transient"  # New instance per request
         | 
| 32 | 
            -
                SCOPED = "scoped" | 
| 34 | 
            +
                SCOPED = "scoped"  # One instance per scope
         | 
| 33 35 |  | 
| 34 36 |  | 
| 35 37 | 
             
            class ServiceRegistration:
         | 
| 36 38 | 
             
                """Represents a service registration in the container."""
         | 
| 37 | 
            -
             | 
| 39 | 
            +
             | 
| 38 40 | 
             
                def __init__(
         | 
| 39 41 | 
             
                    self,
         | 
| 40 42 | 
             
                    service_type: Type,
         | 
| @@ -42,11 +44,11 @@ class ServiceRegistration: | |
| 42 44 | 
             
                    factory: Optional[Callable] = None,
         | 
| 43 45 | 
             
                    instance: Optional[Any] = None,
         | 
| 44 46 | 
             
                    lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
         | 
| 45 | 
            -
                    dependencies: Optional[Dict[str, Type]] = None
         | 
| 47 | 
            +
                    dependencies: Optional[Dict[str, Type]] = None,
         | 
| 46 48 | 
             
                ):
         | 
| 47 49 | 
             
                    """
         | 
| 48 50 | 
             
                    Initialize service registration.
         | 
| 49 | 
            -
             | 
| 51 | 
            +
             | 
| 50 52 | 
             
                    Args:
         | 
| 51 53 | 
             
                        service_type: The interface/base type being registered
         | 
| 52 54 | 
             
                        implementation: The concrete implementation class
         | 
| @@ -62,15 +64,15 @@ class ServiceRegistration: | |
| 62 64 | 
             
                    self.lifetime = lifetime
         | 
| 63 65 | 
             
                    self.dependencies = dependencies or {}
         | 
| 64 66 | 
             
                    self._lock = threading.Lock()
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                def create_instance(self, container:  | 
| 67 | 
            +
             | 
| 68 | 
            +
                def create_instance(self, container: "DIContainer") -> Any:
         | 
| 67 69 | 
             
                    """Create an instance of the service."""
         | 
| 68 70 | 
             
                    if self.instance is not None:
         | 
| 69 71 | 
             
                        return self.instance
         | 
| 70 | 
            -
             | 
| 72 | 
            +
             | 
| 71 73 | 
             
                    if self.factory:
         | 
| 72 74 | 
             
                        return self.factory(container)
         | 
| 73 | 
            -
             | 
| 75 | 
            +
             | 
| 74 76 | 
             
                    # Get constructor parameters
         | 
| 75 77 | 
             
                    if inspect.isclass(self.implementation):
         | 
| 76 78 | 
             
                        return container.create_instance(self.implementation, self.dependencies)
         | 
| @@ -81,65 +83,69 @@ class ServiceRegistration: | |
| 81 83 |  | 
| 82 84 | 
             
            class CircularDependencyError(Exception):
         | 
| 83 85 | 
             
                """Raised when circular dependencies are detected."""
         | 
| 86 | 
            +
             | 
| 84 87 | 
             
                pass
         | 
| 85 88 |  | 
| 86 89 |  | 
| 87 90 | 
             
            class ServiceNotFoundError(Exception):
         | 
| 88 91 | 
             
                """Raised when a requested service is not registered."""
         | 
| 92 | 
            +
             | 
| 89 93 | 
             
                pass
         | 
| 90 94 |  | 
| 91 95 |  | 
| 92 96 | 
             
            class ServiceScope:
         | 
| 93 97 | 
             
                """
         | 
| 94 98 | 
             
                Represents a service scope for scoped lifetime services.
         | 
| 95 | 
            -
             | 
| 99 | 
            +
             | 
| 96 100 | 
             
                Scoped services live for the duration of the scope and are shared
         | 
| 97 101 | 
             
                within that scope.
         | 
| 98 102 | 
             
                """
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                def __init__(self, container:  | 
| 103 | 
            +
             | 
| 104 | 
            +
                def __init__(self, container: "DIContainer"):
         | 
| 101 105 | 
             
                    """Initialize service scope."""
         | 
| 102 106 | 
             
                    self._container = container
         | 
| 103 107 | 
             
                    self._scoped_instances: Dict[Type, Any] = {}
         | 
| 104 108 | 
             
                    self._disposed = False
         | 
| 105 109 | 
             
                    self._lock = threading.Lock()
         | 
| 106 | 
            -
             | 
| 110 | 
            +
             | 
| 107 111 | 
             
                def get_scoped_instance(self, service_type: Type) -> Optional[Any]:
         | 
| 108 112 | 
             
                    """Get scoped instance if exists."""
         | 
| 109 113 | 
             
                    with self._lock:
         | 
| 110 114 | 
             
                        return self._scoped_instances.get(service_type)
         | 
| 111 | 
            -
             | 
| 115 | 
            +
             | 
| 112 116 | 
             
                def set_scoped_instance(self, service_type: Type, instance: Any) -> None:
         | 
| 113 117 | 
             
                    """Store scoped instance."""
         | 
| 114 118 | 
             
                    with self._lock:
         | 
| 115 119 | 
             
                        if not self._disposed:
         | 
| 116 120 | 
             
                            self._scoped_instances[service_type] = instance
         | 
| 117 | 
            -
             | 
| 121 | 
            +
             | 
| 118 122 | 
             
                def dispose(self) -> None:
         | 
| 119 123 | 
             
                    """
         | 
| 120 124 | 
             
                    Dispose of the scope and all scoped instances.
         | 
| 121 | 
            -
             | 
| 125 | 
            +
             | 
| 122 126 | 
             
                    Calls dispose() on instances that implement IDisposable.
         | 
| 123 127 | 
             
                    """
         | 
| 124 128 | 
             
                    with self._lock:
         | 
| 125 129 | 
             
                        if self._disposed:
         | 
| 126 130 | 
             
                            return
         | 
| 127 | 
            -
             | 
| 131 | 
            +
             | 
| 128 132 | 
             
                        for service_type, instance in self._scoped_instances.items():
         | 
| 129 133 | 
             
                            # Call dispose if available
         | 
| 130 | 
            -
                            if hasattr(instance,  | 
| 134 | 
            +
                            if hasattr(instance, "dispose"):
         | 
| 131 135 | 
             
                                try:
         | 
| 132 136 | 
             
                                    instance.dispose()
         | 
| 133 137 | 
             
                                except Exception as e:
         | 
| 134 | 
            -
                                    logger.error( | 
| 135 | 
            -
             | 
| 138 | 
            +
                                    logger.error(
         | 
| 139 | 
            +
                                        f"Error disposing scoped service {service_type}: {e}"
         | 
| 140 | 
            +
                                    )
         | 
| 141 | 
            +
             | 
| 136 142 | 
             
                        self._scoped_instances.clear()
         | 
| 137 143 | 
             
                        self._disposed = True
         | 
| 138 | 
            -
             | 
| 144 | 
            +
             | 
| 139 145 | 
             
                def __enter__(self):
         | 
| 140 146 | 
             
                    """Context manager entry."""
         | 
| 141 147 | 
             
                    return self
         | 
| 142 | 
            -
             | 
| 148 | 
            +
             | 
| 143 149 | 
             
                def __exit__(self, exc_type, exc_val, exc_tb):
         | 
| 144 150 | 
             
                    """Context manager exit - dispose scope."""
         | 
| 145 151 | 
             
                    self.dispose()
         | 
| @@ -148,10 +154,10 @@ class ServiceScope: | |
| 148 154 | 
             
            class DIContainer(IServiceContainer):
         | 
| 149 155 | 
             
                """
         | 
| 150 156 | 
             
                Enhanced Dependency Injection Container.
         | 
| 151 | 
            -
             | 
| 157 | 
            +
             | 
| 152 158 | 
             
                Implements IServiceContainer interface to provide a complete
         | 
| 153 159 | 
             
                dependency injection solution.
         | 
| 154 | 
            -
             | 
| 160 | 
            +
             | 
| 155 161 | 
             
                Provides:
         | 
| 156 162 | 
             
                - Service registration with multiple lifetime options
         | 
| 157 163 | 
             
                - Automatic constructor injection
         | 
| @@ -163,7 +169,7 @@ class DIContainer(IServiceContainer): | |
| 163 169 | 
             
                - Named registrations
         | 
| 164 170 | 
             
                - Configuration injection
         | 
| 165 171 | 
             
                """
         | 
| 166 | 
            -
             | 
| 172 | 
            +
             | 
| 167 173 | 
             
                def __init__(self):
         | 
| 168 174 | 
             
                    """Initialize the DI container."""
         | 
| 169 175 | 
             
                    self._registrations: Dict[Type, ServiceRegistration] = {}
         | 
| @@ -176,47 +182,42 @@ class DIContainer(IServiceContainer): | |
| 176 182 | 
             
                    self._lock = threading.RLock()
         | 
| 177 183 | 
             
                    self._resolving: Set[Type] = set()
         | 
| 178 184 | 
             
                    self._current_scope: Optional[ServiceScope] = None
         | 
| 179 | 
            -
             | 
| 185 | 
            +
             | 
| 180 186 | 
             
                def register(
         | 
| 181 | 
            -
                    self,
         | 
| 182 | 
            -
                    service_type: type,
         | 
| 183 | 
            -
                    implementation: type,
         | 
| 184 | 
            -
                    singleton: bool = True
         | 
| 187 | 
            +
                    self, service_type: type, implementation: type, singleton: bool = True
         | 
| 185 188 | 
             
                ) -> None:
         | 
| 186 189 | 
             
                    """
         | 
| 187 190 | 
             
                    Register a service implementation (IServiceContainer interface method).
         | 
| 188 | 
            -
             | 
| 191 | 
            +
             | 
| 189 192 | 
             
                    Args:
         | 
| 190 193 | 
             
                        service_type: The interface/base type to register
         | 
| 191 194 | 
             
                        implementation: The concrete implementation class
         | 
| 192 195 | 
             
                        singleton: Whether to use singleton lifetime (default True)
         | 
| 193 | 
            -
             | 
| 196 | 
            +
             | 
| 194 197 | 
             
                    Examples:
         | 
| 195 198 | 
             
                        # Register interface with implementation
         | 
| 196 199 | 
             
                        container.register(ILogger, ConsoleLogger)
         | 
| 197 | 
            -
             | 
| 200 | 
            +
             | 
| 198 201 | 
             
                        # Register as transient (new instance each time)
         | 
| 199 202 | 
             
                        container.register(IService, ServiceImpl, singleton=False)
         | 
| 200 203 | 
             
                    """
         | 
| 201 204 | 
             
                    lifetime = ServiceLifetime.SINGLETON if singleton else ServiceLifetime.TRANSIENT
         | 
| 202 205 | 
             
                    self._register_internal(
         | 
| 203 | 
            -
                        service_type=service_type,
         | 
| 204 | 
            -
                        implementation=implementation,
         | 
| 205 | 
            -
                        lifetime=lifetime
         | 
| 206 | 
            +
                        service_type=service_type, implementation=implementation, lifetime=lifetime
         | 
| 206 207 | 
             
                    )
         | 
| 207 | 
            -
             | 
| 208 | 
            +
             | 
| 208 209 | 
             
                def _register_internal(
         | 
| 209 210 | 
             
                    self,
         | 
| 210 211 | 
             
                    service_type: Type[T],
         | 
| 211 212 | 
             
                    implementation: Optional[Union[Type[T], Callable[..., T]]] = None,
         | 
| 212 213 | 
             
                    lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
         | 
| 213 | 
            -
                    factory: Optional[Callable[[ | 
| 214 | 
            +
                    factory: Optional[Callable[["DIContainer"], T]] = None,
         | 
| 214 215 | 
             
                    instance: Optional[T] = None,
         | 
| 215 | 
            -
                    dependencies: Optional[Dict[str, Type]] = None
         | 
| 216 | 
            +
                    dependencies: Optional[Dict[str, Type]] = None,
         | 
| 216 217 | 
             
                ) -> None:
         | 
| 217 218 | 
             
                    """
         | 
| 218 219 | 
             
                    Internal registration method with full flexibility.
         | 
| 219 | 
            -
             | 
| 220 | 
            +
             | 
| 220 221 | 
             
                    Args:
         | 
| 221 222 | 
             
                        service_type: The interface/base type to register
         | 
| 222 223 | 
             
                        implementation: The concrete implementation (class or factory)
         | 
| @@ -232,22 +233,22 @@ class DIContainer(IServiceContainer): | |
| 232 233 | 
             
                            factory=factory,
         | 
| 233 234 | 
             
                            instance=instance,
         | 
| 234 235 | 
             
                            lifetime=lifetime,
         | 
| 235 | 
            -
                            dependencies=dependencies
         | 
| 236 | 
            +
                            dependencies=dependencies,
         | 
| 236 237 | 
             
                        )
         | 
| 237 238 | 
             
                        self._registrations[service_type] = registration
         | 
| 238 | 
            -
             | 
| 239 | 
            +
             | 
| 239 240 | 
             
                        # If instance provided, store as singleton
         | 
| 240 241 | 
             
                        if instance is not None:
         | 
| 241 242 | 
             
                            self._singletons[service_type] = instance
         | 
| 242 | 
            -
             | 
| 243 | 
            +
             | 
| 243 244 | 
             
                def register_instance(self, service_type: type, instance: Any) -> None:
         | 
| 244 245 | 
             
                    """
         | 
| 245 246 | 
             
                    Register a service instance (IServiceContainer interface method).
         | 
| 246 | 
            -
             | 
| 247 | 
            +
             | 
| 247 248 | 
             
                    Args:
         | 
| 248 249 | 
             
                        service_type: The interface/base type to register
         | 
| 249 250 | 
             
                        instance: Pre-created instance to register as singleton
         | 
| 250 | 
            -
             | 
| 251 | 
            +
             | 
| 251 252 | 
             
                    Examples:
         | 
| 252 253 | 
             
                        # Register a pre-created instance
         | 
| 253 254 | 
             
                        config = Config()
         | 
| @@ -256,24 +257,24 @@ class DIContainer(IServiceContainer): | |
| 256 257 | 
             
                    self._register_internal(
         | 
| 257 258 | 
             
                        service_type=service_type,
         | 
| 258 259 | 
             
                        instance=instance,
         | 
| 259 | 
            -
                        lifetime=ServiceLifetime.SINGLETON
         | 
| 260 | 
            +
                        lifetime=ServiceLifetime.SINGLETON,
         | 
| 260 261 | 
             
                    )
         | 
| 261 | 
            -
             | 
| 262 | 
            +
             | 
| 262 263 | 
             
                def resolve_all(self, service_type: type) -> List[Any]:
         | 
| 263 264 | 
             
                    """
         | 
| 264 265 | 
             
                    Resolve all implementations of a service type (IServiceContainer interface method).
         | 
| 265 | 
            -
             | 
| 266 | 
            +
             | 
| 266 267 | 
             
                    Args:
         | 
| 267 268 | 
             
                        service_type: The type to resolve
         | 
| 268 | 
            -
             | 
| 269 | 
            +
             | 
| 269 270 | 
             
                    Returns:
         | 
| 270 271 | 
             
                        List of all registered implementations for the service type
         | 
| 271 | 
            -
             | 
| 272 | 
            +
             | 
| 272 273 | 
             
                    Examples:
         | 
| 273 274 | 
             
                        # Register multiple implementations
         | 
| 274 275 | 
             
                        container.register(IPlugin, PluginA)
         | 
| 275 276 | 
             
                        container.register(IPlugin, PluginB)
         | 
| 276 | 
            -
             | 
| 277 | 
            +
             | 
| 277 278 | 
             
                        # Get all implementations
         | 
| 278 279 | 
             
                        plugins = container.resolve_all(IPlugin)
         | 
| 279 280 | 
             
                    """
         | 
| @@ -283,32 +284,32 @@ class DIContainer(IServiceContainer): | |
| 283 284 | 
             
                        if service_type in self._registrations:
         | 
| 284 285 | 
             
                            return [self._resolve_internal(service_type)]
         | 
| 285 286 | 
             
                        return []
         | 
| 286 | 
            -
             | 
| 287 | 
            +
             | 
| 287 288 | 
             
                def register_singleton(
         | 
| 288 289 | 
             
                    self,
         | 
| 289 290 | 
             
                    interface: Type[T],
         | 
| 290 291 | 
             
                    implementation: Optional[Union[Type[T], T]] = None,
         | 
| 291 292 | 
             
                    instance: Optional[T] = None,
         | 
| 292 293 | 
             
                    name: Optional[str] = None,
         | 
| 293 | 
            -
                    dispose_handler: Optional[Callable[[T], None]] = None
         | 
| 294 | 
            +
                    dispose_handler: Optional[Callable[[T], None]] = None,
         | 
| 294 295 | 
             
                ) -> None:
         | 
| 295 296 | 
             
                    """
         | 
| 296 297 | 
             
                    Register a singleton service.
         | 
| 297 | 
            -
             | 
| 298 | 
            +
             | 
| 298 299 | 
             
                    Args:
         | 
| 299 300 | 
             
                        interface: The interface/base type to register
         | 
| 300 301 | 
             
                        implementation: The concrete implementation class
         | 
| 301 302 | 
             
                        instance: Pre-created instance (alternative to implementation)
         | 
| 302 303 | 
             
                        name: Optional name for named registration
         | 
| 303 304 | 
             
                        dispose_handler: Optional handler called when disposing service
         | 
| 304 | 
            -
             | 
| 305 | 
            +
             | 
| 305 306 | 
             
                    Examples:
         | 
| 306 307 | 
             
                        # Register with implementation class
         | 
| 307 308 | 
             
                        container.register_singleton(ILogger, ConsoleLogger)
         | 
| 308 | 
            -
             | 
| 309 | 
            +
             | 
| 309 310 | 
             
                        # Register with instance
         | 
| 310 311 | 
             
                        container.register_singleton(IConfig, instance=Config())
         | 
| 311 | 
            -
             | 
| 312 | 
            +
             | 
| 312 313 | 
             
                        # Register with disposal handler
         | 
| 313 314 | 
             
                        container.register_singleton(
         | 
| 314 315 | 
             
                            IDatabase,
         | 
| @@ -323,15 +324,15 @@ class DIContainer(IServiceContainer): | |
| 323 324 | 
             
                            service_type=interface,
         | 
| 324 325 | 
             
                            implementation=implementation,
         | 
| 325 326 | 
             
                            instance=instance,
         | 
| 326 | 
            -
                            lifetime=ServiceLifetime.SINGLETON
         | 
| 327 | 
            +
                            lifetime=ServiceLifetime.SINGLETON,
         | 
| 327 328 | 
             
                        )
         | 
| 328 329 | 
             
                        self._named_registrations[name] = registration
         | 
| 329 | 
            -
             | 
| 330 | 
            +
             | 
| 330 331 | 
             
                        # Also store the instance if provided
         | 
| 331 332 | 
             
                        if instance is not None:
         | 
| 332 333 | 
             
                            # Store with a composite key for retrieval
         | 
| 333 334 | 
             
                            named_key = (interface, name)
         | 
| 334 | 
            -
                            if not hasattr(self,  | 
| 335 | 
            +
                            if not hasattr(self, "_named_singletons"):
         | 
| 335 336 | 
             
                                self._named_singletons = {}
         | 
| 336 337 | 
             
                            self._named_singletons[named_key] = instance
         | 
| 337 338 | 
             
                    else:
         | 
| @@ -342,82 +343,86 @@ class DIContainer(IServiceContainer): | |
| 342 343 | 
             
                            # It's an instance passed as implementation (backward compatibility)
         | 
| 343 344 | 
             
                            self._register_internal(interface, instance=implementation)
         | 
| 344 345 | 
             
                        else:
         | 
| 345 | 
            -
                            self._register_internal( | 
| 346 | 
            -
             | 
| 346 | 
            +
                            self._register_internal(
         | 
| 347 | 
            +
                                interface, implementation, lifetime=ServiceLifetime.SINGLETON
         | 
| 348 | 
            +
                            )
         | 
| 349 | 
            +
             | 
| 347 350 | 
             
                    # Handle disposal handler
         | 
| 348 351 | 
             
                    if dispose_handler:
         | 
| 349 352 | 
             
                        if name:
         | 
| 350 353 | 
             
                            # Store with composite key for named services
         | 
| 351 | 
            -
                            if not hasattr(self,  | 
| 354 | 
            +
                            if not hasattr(self, "_named_disposal_handlers"):
         | 
| 352 355 | 
             
                                self._named_disposal_handlers = {}
         | 
| 353 356 | 
             
                            self._named_disposal_handlers[(interface, name)] = dispose_handler
         | 
| 354 357 | 
             
                        else:
         | 
| 355 358 | 
             
                            self._disposal_handlers[interface] = dispose_handler
         | 
| 356 | 
            -
             | 
| 359 | 
            +
             | 
| 357 360 | 
             
                    # Track initialization order for proper disposal
         | 
| 358 361 | 
             
                    key = (interface, name) if name else interface
         | 
| 359 362 | 
             
                    if key not in self._initialization_order:
         | 
| 360 363 | 
             
                        self._initialization_order.append(key)
         | 
| 361 | 
            -
             | 
| 364 | 
            +
             | 
| 362 365 | 
             
                def register_scoped(
         | 
| 363 366 | 
             
                    self,
         | 
| 364 367 | 
             
                    interface: Type[T],
         | 
| 365 368 | 
             
                    implementation: Optional[Type[T]] = None,
         | 
| 366 | 
            -
                    name: Optional[str] = None
         | 
| 369 | 
            +
                    name: Optional[str] = None,
         | 
| 367 370 | 
             
                ) -> None:
         | 
| 368 371 | 
             
                    """
         | 
| 369 372 | 
             
                    Register a scoped service.
         | 
| 370 | 
            -
             | 
| 373 | 
            +
             | 
| 371 374 | 
             
                    Scoped services are created once per scope and shared within that scope.
         | 
| 372 | 
            -
             | 
| 375 | 
            +
             | 
| 373 376 | 
             
                    Args:
         | 
| 374 377 | 
             
                        interface: The interface/base type to register
         | 
| 375 378 | 
             
                        implementation: The concrete implementation
         | 
| 376 379 | 
             
                        name: Optional name for named registration
         | 
| 377 | 
            -
             | 
| 380 | 
            +
             | 
| 378 381 | 
             
                    Examples:
         | 
| 379 382 | 
             
                        # Register scoped service
         | 
| 380 383 | 
             
                        container.register_scoped(IRequestContext, RequestContext)
         | 
| 381 | 
            -
             | 
| 384 | 
            +
             | 
| 382 385 | 
             
                        # Use in scope
         | 
| 383 386 | 
             
                        with container.create_scope() as scope:
         | 
| 384 387 | 
             
                            context = container.get(IRequestContext)  # Created
         | 
| 385 388 | 
             
                            context2 = container.get(IRequestContext)  # Same instance
         | 
| 386 389 | 
             
                    """
         | 
| 387 | 
            -
                    self._register_internal( | 
| 390 | 
            +
                    self._register_internal(
         | 
| 391 | 
            +
                        interface, implementation, lifetime=ServiceLifetime.SCOPED
         | 
| 392 | 
            +
                    )
         | 
| 388 393 | 
             
                    if name:
         | 
| 389 394 | 
             
                        self._named_registrations[name] = self._registrations[interface]
         | 
| 390 | 
            -
             | 
| 395 | 
            +
             | 
| 391 396 | 
             
                def register_transient(
         | 
| 392 | 
            -
                    self,
         | 
| 393 | 
            -
                    service_type: Type[T],
         | 
| 394 | 
            -
                    implementation: Optional[Type[T]] = None
         | 
| 397 | 
            +
                    self, service_type: Type[T], implementation: Optional[Type[T]] = None
         | 
| 395 398 | 
             
                ) -> None:
         | 
| 396 399 | 
             
                    """
         | 
| 397 400 | 
             
                    Register a transient service.
         | 
| 398 | 
            -
             | 
| 401 | 
            +
             | 
| 399 402 | 
             
                    Convenience method for registering transient services.
         | 
| 400 403 | 
             
                    """
         | 
| 401 | 
            -
                    self._register_internal( | 
| 402 | 
            -
             | 
| 404 | 
            +
                    self._register_internal(
         | 
| 405 | 
            +
                        service_type, implementation, lifetime=ServiceLifetime.TRANSIENT
         | 
| 406 | 
            +
                    )
         | 
| 407 | 
            +
             | 
| 403 408 | 
             
                def register_factory(
         | 
| 404 409 | 
             
                    self,
         | 
| 405 410 | 
             
                    interface: Type[T],
         | 
| 406 | 
            -
                    factory: Callable[[ | 
| 411 | 
            +
                    factory: Callable[["DIContainer"], T],
         | 
| 407 412 | 
             
                    lifetime: ServiceLifetime = ServiceLifetime.TRANSIENT,
         | 
| 408 | 
            -
                    name: Optional[str] = None
         | 
| 413 | 
            +
                    name: Optional[str] = None,
         | 
| 409 414 | 
             
                ) -> None:
         | 
| 410 415 | 
             
                    """
         | 
| 411 416 | 
             
                    Register a service with a factory function.
         | 
| 412 | 
            -
             | 
| 417 | 
            +
             | 
| 413 418 | 
             
                    The factory receives the container as parameter for resolving dependencies.
         | 
| 414 | 
            -
             | 
| 419 | 
            +
             | 
| 415 420 | 
             
                    Args:
         | 
| 416 421 | 
             
                        interface: The interface/base type to register
         | 
| 417 422 | 
             
                        factory: Factory function that creates instances
         | 
| 418 423 | 
             
                        lifetime: Service lifetime (default: TRANSIENT for factories)
         | 
| 419 424 | 
             
                        name: Optional name for named registration
         | 
| 420 | 
            -
             | 
| 425 | 
            +
             | 
| 421 426 | 
             
                    Examples:
         | 
| 422 427 | 
             
                        # Register with factory
         | 
| 423 428 | 
             
                        container.register_factory(
         | 
| @@ -430,29 +435,29 @@ class DIContainer(IServiceContainer): | |
| 430 435 | 
             
                    self._factories[interface] = factory
         | 
| 431 436 | 
             
                    if name:
         | 
| 432 437 | 
             
                        self._named_registrations[name] = self._registrations[interface]
         | 
| 433 | 
            -
             | 
| 438 | 
            +
             | 
| 434 439 | 
             
                def get(self, interface: Type[T], name: Optional[str] = None) -> T:
         | 
| 435 440 | 
             
                    """
         | 
| 436 441 | 
             
                    Get service instance with dependency resolution.
         | 
| 437 | 
            -
             | 
| 442 | 
            +
             | 
| 438 443 | 
             
                    This is the primary method for retrieving services from the container.
         | 
| 439 444 | 
             
                    It handles all lifetime management and dependency resolution.
         | 
| 440 | 
            -
             | 
| 445 | 
            +
             | 
| 441 446 | 
             
                    Args:
         | 
| 442 447 | 
             
                        interface: The type to resolve
         | 
| 443 448 | 
             
                        name: Optional name for named registration lookup
         | 
| 444 | 
            -
             | 
| 449 | 
            +
             | 
| 445 450 | 
             
                    Returns:
         | 
| 446 451 | 
             
                        Instance of the requested service
         | 
| 447 | 
            -
             | 
| 452 | 
            +
             | 
| 448 453 | 
             
                    Raises:
         | 
| 449 454 | 
             
                        ServiceNotFoundError: If service is not registered
         | 
| 450 455 | 
             
                        CircularDependencyError: If circular dependencies detected
         | 
| 451 | 
            -
             | 
| 456 | 
            +
             | 
| 452 457 | 
             
                    Examples:
         | 
| 453 458 | 
             
                        # Get by interface
         | 
| 454 459 | 
             
                        logger = container.get(ILogger)
         | 
| 455 | 
            -
             | 
| 460 | 
            +
             | 
| 456 461 | 
             
                        # Get named service
         | 
| 457 462 | 
             
                        primary_db = container.get(IDatabase, name="primary")
         | 
| 458 463 | 
             
                    """
         | 
| @@ -461,14 +466,19 @@ class DIContainer(IServiceContainer): | |
| 461 466 | 
             
                            suggestions = self._get_similar_names(name)
         | 
| 462 467 | 
             
                            raise ServiceNotFoundError(
         | 
| 463 468 | 
             
                                f"Named service '{name}' is not registered. "
         | 
| 464 | 
            -
                                f"Did you mean: {', '.join(suggestions)}?" | 
| 469 | 
            +
                                f"Did you mean: {', '.join(suggestions)}?"
         | 
| 470 | 
            +
                                if suggestions
         | 
| 471 | 
            +
                                else ""
         | 
| 465 472 | 
             
                            )
         | 
| 466 | 
            -
             | 
| 473 | 
            +
             | 
| 467 474 | 
             
                        # Check if we have a pre-stored instance for this named service
         | 
| 468 475 | 
             
                        named_key = (interface, name)
         | 
| 469 | 
            -
                        if  | 
| 476 | 
            +
                        if (
         | 
| 477 | 
            +
                            hasattr(self, "_named_singletons")
         | 
| 478 | 
            +
                            and named_key in self._named_singletons
         | 
| 479 | 
            +
                        ):
         | 
| 470 480 | 
             
                            return self._named_singletons[named_key]
         | 
| 471 | 
            -
             | 
| 481 | 
            +
             | 
| 472 482 | 
             
                        # Otherwise resolve from named registration
         | 
| 473 483 | 
             
                        registration = self._named_registrations[name]
         | 
| 474 484 | 
             
                        if registration.instance is not None:
         | 
| @@ -476,41 +486,46 @@ class DIContainer(IServiceContainer): | |
| 476 486 | 
             
                        elif registration.factory:
         | 
| 477 487 | 
             
                            return registration.factory(self)
         | 
| 478 488 | 
             
                        else:
         | 
| 479 | 
            -
                            return self.create_instance( | 
| 480 | 
            -
                                
         | 
| 489 | 
            +
                            return self.create_instance(
         | 
| 490 | 
            +
                                registration.implementation, registration.dependencies
         | 
| 491 | 
            +
                            )
         | 
| 492 | 
            +
             | 
| 481 493 | 
             
                    return self._resolve_internal(interface)
         | 
| 482 | 
            -
             | 
| 494 | 
            +
             | 
| 483 495 | 
             
                def resolve(self, service_type: Type[T]) -> T:
         | 
| 484 496 | 
             
                    """
         | 
| 485 497 | 
             
                    Resolve a service from the container (legacy method).
         | 
| 486 | 
            -
             | 
| 498 | 
            +
             | 
| 487 499 | 
             
                    This method is maintained for backward compatibility.
         | 
| 488 500 | 
             
                    New code should use get() instead.
         | 
| 489 | 
            -
             | 
| 501 | 
            +
             | 
| 490 502 | 
             
                    Args:
         | 
| 491 503 | 
             
                        service_type: The type to resolve
         | 
| 492 | 
            -
             | 
| 504 | 
            +
             | 
| 493 505 | 
             
                    Returns:
         | 
| 494 506 | 
             
                        Instance of the requested service
         | 
| 495 | 
            -
             | 
| 507 | 
            +
             | 
| 496 508 | 
             
                    Raises:
         | 
| 497 509 | 
             
                        ServiceNotFoundError: If service is not registered
         | 
| 498 510 | 
             
                        CircularDependencyError: If circular dependencies detected
         | 
| 499 511 | 
             
                    """
         | 
| 500 512 | 
             
                    return self.get(service_type)
         | 
| 501 | 
            -
             | 
| 513 | 
            +
             | 
| 502 514 | 
             
                def _resolve_internal(self, service_type: Type[T]) -> T:
         | 
| 503 515 | 
             
                    """
         | 
| 504 516 | 
             
                    Internal method to resolve a service.
         | 
| 505 | 
            -
             | 
| 517 | 
            +
             | 
| 506 518 | 
             
                    Handles the actual resolution logic with proper locking and lifecycle management.
         | 
| 507 519 | 
             
                    """
         | 
| 508 520 | 
             
                    with self._lock:
         | 
| 509 521 | 
             
                        # Check for circular dependencies
         | 
| 510 522 | 
             
                        if service_type in self._resolving:
         | 
| 511 | 
            -
                            cycle =  | 
| 523 | 
            +
                            cycle = (
         | 
| 524 | 
            +
                                " -> ".join(str(t.__name__) for t in self._resolving)
         | 
| 525 | 
            +
                                + f" -> {service_type.__name__}"
         | 
| 526 | 
            +
                            )
         | 
| 512 527 | 
             
                            raise CircularDependencyError(f"Circular dependency detected: {cycle}")
         | 
| 513 | 
            -
             | 
| 528 | 
            +
             | 
| 514 529 | 
             
                        # Check if registered
         | 
| 515 530 | 
             
                        if service_type not in self._registrations:
         | 
| 516 531 | 
             
                            suggestions = self._get_similar_types(service_type)
         | 
| @@ -518,98 +533,105 @@ class DIContainer(IServiceContainer): | |
| 518 533 | 
             
                            if suggestions:
         | 
| 519 534 | 
             
                                error_msg += f" Did you mean: {', '.join(suggestions)}?"
         | 
| 520 535 | 
             
                            raise ServiceNotFoundError(error_msg)
         | 
| 521 | 
            -
             | 
| 536 | 
            +
             | 
| 522 537 | 
             
                        registration = self._registrations[service_type]
         | 
| 523 | 
            -
             | 
| 538 | 
            +
             | 
| 524 539 | 
             
                        # Handle different lifetimes
         | 
| 525 540 | 
             
                        if registration.lifetime == ServiceLifetime.SINGLETON:
         | 
| 526 541 | 
             
                            # Return existing singleton if available
         | 
| 527 542 | 
             
                            if service_type in self._singletons:
         | 
| 528 543 | 
             
                                return self._singletons[service_type]
         | 
| 529 | 
            -
             | 
| 544 | 
            +
             | 
| 530 545 | 
             
                        elif registration.lifetime == ServiceLifetime.SCOPED:
         | 
| 531 546 | 
             
                            # Check current scope
         | 
| 532 547 | 
             
                            if self._current_scope:
         | 
| 533 548 | 
             
                                instance = self._current_scope.get_scoped_instance(service_type)
         | 
| 534 549 | 
             
                                if instance is not None:
         | 
| 535 550 | 
             
                                    return instance
         | 
| 536 | 
            -
             | 
| 551 | 
            +
             | 
| 537 552 | 
             
                        # Mark as resolving
         | 
| 538 553 | 
             
                        self._resolving.add(service_type)
         | 
| 539 | 
            -
             | 
| 554 | 
            +
             | 
| 540 555 | 
             
                        try:
         | 
| 541 556 | 
             
                            # Create instance
         | 
| 542 557 | 
             
                            instance = registration.create_instance(self)
         | 
| 543 | 
            -
             | 
| 558 | 
            +
             | 
| 544 559 | 
             
                            # Store based on lifetime
         | 
| 545 560 | 
             
                            if registration.lifetime == ServiceLifetime.SINGLETON:
         | 
| 546 561 | 
             
                                self._singletons[service_type] = instance
         | 
| 547 562 | 
             
                                if service_type not in self._initialization_order:
         | 
| 548 563 | 
             
                                    self._initialization_order.append(service_type)
         | 
| 549 | 
            -
             | 
| 564 | 
            +
             | 
| 550 565 | 
             
                            elif registration.lifetime == ServiceLifetime.SCOPED:
         | 
| 551 566 | 
             
                                if self._current_scope:
         | 
| 552 567 | 
             
                                    self._current_scope.set_scoped_instance(service_type, instance)
         | 
| 553 | 
            -
             | 
| 568 | 
            +
             | 
| 554 569 | 
             
                            # Call initialization hook if available
         | 
| 555 | 
            -
                            if hasattr(instance,  | 
| 570 | 
            +
                            if hasattr(instance, "initialize"):
         | 
| 556 571 | 
             
                                try:
         | 
| 557 572 | 
             
                                    instance.initialize()
         | 
| 558 573 | 
             
                                except Exception as e:
         | 
| 559 | 
            -
                                    logger.error( | 
| 574 | 
            +
                                    logger.error(
         | 
| 575 | 
            +
                                        f"Failed to initialize service {service_type.__name__}: {e}"
         | 
| 576 | 
            +
                                    )
         | 
| 560 577 | 
             
                                    raise
         | 
| 561 | 
            -
             | 
| 578 | 
            +
             | 
| 562 579 | 
             
                            return instance
         | 
| 563 | 
            -
             | 
| 580 | 
            +
             | 
| 564 581 | 
             
                        finally:
         | 
| 565 582 | 
             
                            self._resolving.remove(service_type)
         | 
| 566 | 
            -
             | 
| 567 | 
            -
                def resolve_optional( | 
| 583 | 
            +
             | 
| 584 | 
            +
                def resolve_optional(
         | 
| 585 | 
            +
                    self, service_type: Type[T], default: Optional[T] = None
         | 
| 586 | 
            +
                ) -> Optional[T]:
         | 
| 568 587 | 
             
                    """
         | 
| 569 588 | 
             
                    Resolve a service if registered, otherwise return default.
         | 
| 570 | 
            -
             | 
| 589 | 
            +
             | 
| 571 590 | 
             
                    Useful for optional dependencies.
         | 
| 572 591 | 
             
                    """
         | 
| 573 592 | 
             
                    try:
         | 
| 574 593 | 
             
                        return self.resolve(service_type)
         | 
| 575 594 | 
             
                    except ServiceNotFoundError:
         | 
| 576 595 | 
             
                        return default
         | 
| 577 | 
            -
             | 
| 578 | 
            -
                def create_instance( | 
| 596 | 
            +
             | 
| 597 | 
            +
                def create_instance(
         | 
| 598 | 
            +
                    self, cls: Type[T], explicit_deps: Optional[Dict[str, Type]] = None
         | 
| 599 | 
            +
                ) -> T:
         | 
| 579 600 | 
             
                    """
         | 
| 580 601 | 
             
                    Create an instance of a class, resolving constructor dependencies.
         | 
| 581 | 
            -
             | 
| 602 | 
            +
             | 
| 582 603 | 
             
                    Args:
         | 
| 583 604 | 
             
                        cls: The class to instantiate
         | 
| 584 605 | 
             
                        explicit_deps: Explicit dependency mapping for constructor params
         | 
| 585 | 
            -
             | 
| 606 | 
            +
             | 
| 586 607 | 
             
                    Returns:
         | 
| 587 608 | 
             
                        New instance with resolved dependencies
         | 
| 588 609 | 
             
                    """
         | 
| 589 610 | 
             
                    # Get constructor signature
         | 
| 590 611 | 
             
                    sig = inspect.signature(cls.__init__)
         | 
| 591 612 | 
             
                    kwargs = {}
         | 
| 592 | 
            -
             | 
| 613 | 
            +
             | 
| 593 614 | 
             
                    for param_name, param in sig.parameters.items():
         | 
| 594 | 
            -
                        if param_name ==  | 
| 615 | 
            +
                        if param_name == "self":
         | 
| 595 616 | 
             
                            continue
         | 
| 596 | 
            -
             | 
| 617 | 
            +
             | 
| 597 618 | 
             
                        # Check explicit dependencies first
         | 
| 598 619 | 
             
                        if explicit_deps and param_name in explicit_deps:
         | 
| 599 620 | 
             
                            dep_type = explicit_deps[param_name]
         | 
| 600 621 | 
             
                            kwargs[param_name] = self.resolve(dep_type)
         | 
| 601 622 | 
             
                            continue
         | 
| 602 | 
            -
             | 
| 623 | 
            +
             | 
| 603 624 | 
             
                        # Try to resolve by type annotation
         | 
| 604 625 | 
             
                        if param.annotation != param.empty:
         | 
| 605 626 | 
             
                            param_type = param.annotation
         | 
| 606 | 
            -
             | 
| 627 | 
            +
             | 
| 607 628 | 
             
                            # Handle string annotations (forward references)
         | 
| 608 629 | 
             
                            if isinstance(param_type, str):
         | 
| 609 630 | 
             
                                # Try to resolve forward reference
         | 
| 610 631 | 
             
                                try:
         | 
| 611 632 | 
             
                                    # Get the module where the class is defined
         | 
| 612 633 | 
             
                                    import sys
         | 
| 634 | 
            +
             | 
| 613 635 | 
             
                                    frame = sys._getframe(1)
         | 
| 614 636 | 
             
                                    module = frame.f_globals
         | 
| 615 637 | 
             
                                    if param_type in module:
         | 
| @@ -625,45 +647,52 @@ class DIContainer(IServiceContainer): | |
| 625 647 | 
             
                                    if param.default != param.empty:
         | 
| 626 648 | 
             
                                        kwargs[param_name] = param.default
         | 
| 627 649 | 
             
                                    continue
         | 
| 628 | 
            -
             | 
| 650 | 
            +
             | 
| 629 651 | 
             
                            # Handle Optional types
         | 
| 630 | 
            -
                            if hasattr(param_type,  | 
| 652 | 
            +
                            if hasattr(param_type, "__origin__") and param_type.__origin__ is Union:
         | 
| 631 653 | 
             
                                # Get the non-None type from Optional
         | 
| 632 654 | 
             
                                args = param_type.__args__
         | 
| 633 | 
            -
                                param_type = next( | 
| 634 | 
            -
             | 
| 655 | 
            +
                                param_type = next(
         | 
| 656 | 
            +
                                    (arg for arg in args if arg is not type(None)), None
         | 
| 657 | 
            +
                                )
         | 
| 658 | 
            +
             | 
| 635 659 | 
             
                            if param_type and param_type in self._registrations:
         | 
| 636 660 | 
             
                                # Check for circular dependency
         | 
| 637 661 | 
             
                                if param_type in self._resolving:
         | 
| 638 662 | 
             
                                    # Circular dependency detected
         | 
| 639 | 
            -
                                    cycle =  | 
| 640 | 
            -
             | 
| 663 | 
            +
                                    cycle = (
         | 
| 664 | 
            +
                                        " -> ".join(str(t.__name__) for t in self._resolving)
         | 
| 665 | 
            +
                                        + f" -> {param_type.__name__}"
         | 
| 666 | 
            +
                                    )
         | 
| 667 | 
            +
                                    raise CircularDependencyError(
         | 
| 668 | 
            +
                                        f"Circular dependency detected: {cycle}"
         | 
| 669 | 
            +
                                    )
         | 
| 641 670 | 
             
                                else:
         | 
| 642 671 | 
             
                                    kwargs[param_name] = self.resolve(param_type)
         | 
| 643 672 | 
             
                            elif param.default != param.empty:
         | 
| 644 673 | 
             
                                # Use default value
         | 
| 645 674 | 
             
                                kwargs[param_name] = param.default
         | 
| 646 | 
            -
             | 
| 675 | 
            +
             | 
| 647 676 | 
             
                    return cls(**kwargs)
         | 
| 648 | 
            -
             | 
| 677 | 
            +
             | 
| 649 678 | 
             
                def is_registered(self, service_type: Type) -> bool:
         | 
| 650 679 | 
             
                    """Check if a service type is registered."""
         | 
| 651 680 | 
             
                    return service_type in self._registrations
         | 
| 652 | 
            -
             | 
| 681 | 
            +
             | 
| 653 682 | 
             
                def get_all_registrations(self) -> Dict[Type, ServiceRegistration]:
         | 
| 654 683 | 
             
                    """Get all service registrations."""
         | 
| 655 684 | 
             
                    with self._lock:
         | 
| 656 685 | 
             
                        return self._registrations.copy()
         | 
| 657 | 
            -
             | 
| 686 | 
            +
             | 
| 658 687 | 
             
                def create_scope(self) -> ServiceScope:
         | 
| 659 688 | 
             
                    """
         | 
| 660 689 | 
             
                    Create a new service scope.
         | 
| 661 | 
            -
             | 
| 690 | 
            +
             | 
| 662 691 | 
             
                    Scoped services will be created once per scope and shared within that scope.
         | 
| 663 | 
            -
             | 
| 692 | 
            +
             | 
| 664 693 | 
             
                    Returns:
         | 
| 665 694 | 
             
                        New ServiceScope instance
         | 
| 666 | 
            -
             | 
| 695 | 
            +
             | 
| 667 696 | 
             
                    Examples:
         | 
| 668 697 | 
             
                        # Use scope with context manager
         | 
| 669 698 | 
             
                        with container.create_scope() as scope:
         | 
| @@ -671,7 +700,7 @@ class DIContainer(IServiceContainer): | |
| 671 700 | 
             
                            service1 = container.get(IScopedService)
         | 
| 672 701 | 
             
                            service2 = container.get(IScopedService)
         | 
| 673 702 | 
             
                            assert service1 is service2  # Same instance
         | 
| 674 | 
            -
             | 
| 703 | 
            +
             | 
| 675 704 | 
             
                        # Scope is disposed, scoped instances are cleaned up
         | 
| 676 705 | 
             
                    """
         | 
| 677 706 | 
             
                    scope = ServiceScope(self)
         | 
| @@ -680,30 +709,30 @@ class DIContainer(IServiceContainer): | |
| 680 709 | 
             
                        # Set as current scope for resolution
         | 
| 681 710 | 
             
                        old_scope = self._current_scope
         | 
| 682 711 | 
             
                        self._current_scope = scope
         | 
| 683 | 
            -
             | 
| 712 | 
            +
             | 
| 684 713 | 
             
                    # Return a context manager that restores old scope
         | 
| 685 714 | 
             
                    class ScopeContext:
         | 
| 686 715 | 
             
                        def __init__(self, container, new_scope, old_scope):
         | 
| 687 716 | 
             
                            self.container = container
         | 
| 688 717 | 
             
                            self.new_scope = new_scope
         | 
| 689 718 | 
             
                            self.old_scope = old_scope
         | 
| 690 | 
            -
             | 
| 719 | 
            +
             | 
| 691 720 | 
             
                        def __enter__(self):
         | 
| 692 721 | 
             
                            return self.new_scope
         | 
| 693 | 
            -
             | 
| 722 | 
            +
             | 
| 694 723 | 
             
                        def __exit__(self, exc_type, exc_val, exc_tb):
         | 
| 695 724 | 
             
                            with self.container._lock:
         | 
| 696 725 | 
             
                                self.container._current_scope = self.old_scope
         | 
| 697 726 | 
             
                                if self.new_scope in self.container._scopes:
         | 
| 698 727 | 
             
                                    self.container._scopes.remove(self.new_scope)
         | 
| 699 728 | 
             
                            self.new_scope.dispose()
         | 
| 700 | 
            -
             | 
| 729 | 
            +
             | 
| 701 730 | 
             
                    return ScopeContext(self, scope, old_scope)
         | 
| 702 | 
            -
             | 
| 703 | 
            -
                def create_child_container(self) ->  | 
| 731 | 
            +
             | 
| 732 | 
            +
                def create_child_container(self) -> "DIContainer":
         | 
| 704 733 | 
             
                    """
         | 
| 705 734 | 
             
                    Create a child container that inherits registrations.
         | 
| 706 | 
            -
             | 
| 735 | 
            +
             | 
| 707 736 | 
             
                    Useful for isolated scenarios where you want separate singleton instances.
         | 
| 708 737 | 
             
                    """
         | 
| 709 738 | 
             
                    child = DIContainer()
         | 
| @@ -718,11 +747,11 @@ class DIContainer(IServiceContainer): | |
| 718 747 | 
             
                        # Copy disposal handlers
         | 
| 719 748 | 
             
                        child._disposal_handlers = self._disposal_handlers.copy()
         | 
| 720 749 | 
             
                    return child
         | 
| 721 | 
            -
             | 
| 750 | 
            +
             | 
| 722 751 | 
             
                def dispose(self) -> None:
         | 
| 723 752 | 
             
                    """
         | 
| 724 753 | 
             
                    Dispose of the container and all managed services.
         | 
| 725 | 
            -
             | 
| 754 | 
            +
             | 
| 726 755 | 
             
                    Calls disposal handlers for singleton services in reverse initialization order.
         | 
| 727 756 | 
             
                    Also disposes any active scopes.
         | 
| 728 757 | 
             
                    """
         | 
| @@ -731,31 +760,35 @@ class DIContainer(IServiceContainer): | |
| 731 760 | 
             
                        for scope in reversed(self._scopes):
         | 
| 732 761 | 
             
                            scope.dispose()
         | 
| 733 762 | 
             
                        self._scopes.clear()
         | 
| 734 | 
            -
             | 
| 763 | 
            +
             | 
| 735 764 | 
             
                        # Dispose singletons in reverse initialization order
         | 
| 736 765 | 
             
                        for service_type in reversed(self._initialization_order):
         | 
| 737 766 | 
             
                            if service_type in self._singletons:
         | 
| 738 767 | 
             
                                instance = self._singletons[service_type]
         | 
| 739 | 
            -
             | 
| 768 | 
            +
             | 
| 740 769 | 
             
                                # Call disposal handler if registered
         | 
| 741 770 | 
             
                                if service_type in self._disposal_handlers:
         | 
| 742 771 | 
             
                                    try:
         | 
| 743 772 | 
             
                                        self._disposal_handlers[service_type](instance)
         | 
| 744 773 | 
             
                                    except Exception as e:
         | 
| 745 | 
            -
                                        logger.error( | 
| 746 | 
            -
             | 
| 774 | 
            +
                                        logger.error(
         | 
| 775 | 
            +
                                            f"Error in disposal handler for {service_type.__name__}: {e}"
         | 
| 776 | 
            +
                                        )
         | 
| 777 | 
            +
             | 
| 747 778 | 
             
                                # Call dispose method if available
         | 
| 748 | 
            -
                                elif hasattr(instance,  | 
| 779 | 
            +
                                elif hasattr(instance, "dispose"):
         | 
| 749 780 | 
             
                                    try:
         | 
| 750 781 | 
             
                                        instance.dispose()
         | 
| 751 782 | 
             
                                    except Exception as e:
         | 
| 752 | 
            -
                                        logger.error( | 
| 753 | 
            -
             | 
| 783 | 
            +
                                        logger.error(
         | 
| 784 | 
            +
                                            f"Error disposing service {service_type.__name__}: {e}"
         | 
| 785 | 
            +
                                        )
         | 
| 786 | 
            +
             | 
| 754 787 | 
             
                        # Clear everything
         | 
| 755 788 | 
             
                        self._singletons.clear()
         | 
| 756 789 | 
             
                        self._initialization_order.clear()
         | 
| 757 790 | 
             
                        self._current_scope = None
         | 
| 758 | 
            -
             | 
| 791 | 
            +
             | 
| 759 792 | 
             
                def clear(self) -> None:
         | 
| 760 793 | 
             
                    """Clear all registrations and instances."""
         | 
| 761 794 | 
             
                    self.dispose()
         | 
| @@ -765,28 +798,28 @@ class DIContainer(IServiceContainer): | |
| 765 798 | 
             
                        self._factories.clear()
         | 
| 766 799 | 
             
                        self._disposal_handlers.clear()
         | 
| 767 800 | 
             
                        self._resolving.clear()
         | 
| 768 | 
            -
             | 
| 801 | 
            +
             | 
| 769 802 | 
             
                def _get_similar_types(self, service_type: Type) -> List[str]:
         | 
| 770 803 | 
             
                    """
         | 
| 771 804 | 
             
                    Get similar registered type names for better error messages.
         | 
| 772 | 
            -
             | 
| 805 | 
            +
             | 
| 773 806 | 
             
                    Uses simple string similarity to suggest possible alternatives.
         | 
| 774 807 | 
             
                    """
         | 
| 775 808 | 
             
                    if not self._registrations:
         | 
| 776 809 | 
             
                        return []
         | 
| 777 | 
            -
             | 
| 810 | 
            +
             | 
| 778 811 | 
             
                    type_name = service_type.__name__.lower()
         | 
| 779 812 | 
             
                    similar = []
         | 
| 780 | 
            -
             | 
| 813 | 
            +
             | 
| 781 814 | 
             
                    for registered_type in self._registrations.keys():
         | 
| 782 815 | 
             
                        registered_name = registered_type.__name__
         | 
| 783 816 | 
             
                        registered_lower = registered_name.lower()
         | 
| 784 | 
            -
             | 
| 817 | 
            +
             | 
| 785 818 | 
             
                        # Check for substring match
         | 
| 786 819 | 
             
                        if type_name in registered_lower or registered_lower in type_name:
         | 
| 787 820 | 
             
                            similar.append(registered_name)
         | 
| 788 821 | 
             
                            continue
         | 
| 789 | 
            -
             | 
| 822 | 
            +
             | 
| 790 823 | 
             
                        # Check for common prefix
         | 
| 791 824 | 
             
                        common_prefix_len = 0
         | 
| 792 825 | 
             
                        for i, (a, b) in enumerate(zip(type_name, registered_lower)):
         | 
| @@ -794,30 +827,30 @@ class DIContainer(IServiceContainer): | |
| 794 827 | 
             
                                common_prefix_len = i + 1
         | 
| 795 828 | 
             
                            else:
         | 
| 796 829 | 
             
                                break
         | 
| 797 | 
            -
             | 
| 830 | 
            +
             | 
| 798 831 | 
             
                        if common_prefix_len >= min(3, len(type_name) // 2):
         | 
| 799 832 | 
             
                            similar.append(registered_name)
         | 
| 800 | 
            -
             | 
| 833 | 
            +
             | 
| 801 834 | 
             
                    return similar[:3]  # Return top 3 suggestions
         | 
| 802 | 
            -
             | 
| 835 | 
            +
             | 
| 803 836 | 
             
                def _get_similar_names(self, name: str) -> List[str]:
         | 
| 804 837 | 
             
                    """
         | 
| 805 838 | 
             
                    Get similar registered names for better error messages.
         | 
| 806 839 | 
             
                    """
         | 
| 807 840 | 
             
                    if not self._named_registrations:
         | 
| 808 841 | 
             
                        return []
         | 
| 809 | 
            -
             | 
| 842 | 
            +
             | 
| 810 843 | 
             
                    name_lower = name.lower()
         | 
| 811 844 | 
             
                    similar = []
         | 
| 812 | 
            -
             | 
| 845 | 
            +
             | 
| 813 846 | 
             
                    for registered_name in self._named_registrations.keys():
         | 
| 814 847 | 
             
                        registered_lower = registered_name.lower()
         | 
| 815 | 
            -
             | 
| 848 | 
            +
             | 
| 816 849 | 
             
                        # Check for substring match
         | 
| 817 850 | 
             
                        if name_lower in registered_lower or registered_lower in name_lower:
         | 
| 818 851 | 
             
                            similar.append(registered_name)
         | 
| 819 852 | 
             
                            continue
         | 
| 820 | 
            -
             | 
| 853 | 
            +
             | 
| 821 854 | 
             
                        # Check for common prefix
         | 
| 822 855 | 
             
                        common_prefix_len = 0
         | 
| 823 856 | 
             
                        for i, (a, b) in enumerate(zip(name_lower, registered_lower)):
         | 
| @@ -825,10 +858,10 @@ class DIContainer(IServiceContainer): | |
| 825 858 | 
             
                                common_prefix_len = i + 1
         | 
| 826 859 | 
             
                            else:
         | 
| 827 860 | 
             
                                break
         | 
| 828 | 
            -
             | 
| 861 | 
            +
             | 
| 829 862 | 
             
                        if common_prefix_len >= min(3, len(name_lower) // 2):
         | 
| 830 863 | 
             
                            similar.append(registered_name)
         | 
| 831 | 
            -
             | 
| 864 | 
            +
             | 
| 832 865 | 
             
                    return similar[:3]  # Return top 3 suggestions
         | 
| 833 866 |  | 
| 834 867 |  | 
| @@ -840,7 +873,7 @@ _global_lock = threading.Lock() | |
| 840 873 | 
             
            def get_container() -> DIContainer:
         | 
| 841 874 | 
             
                """
         | 
| 842 875 | 
             
                Get the global DI container instance.
         | 
| 843 | 
            -
             | 
| 876 | 
            +
             | 
| 844 877 | 
             
                Creates one if it doesn't exist.
         | 
| 845 878 | 
             
                """
         | 
| 846 879 | 
             
                global _global_container
         | 
| @@ -854,4 +887,4 @@ def set_container(container: DIContainer) -> None: | |
| 854 887 | 
             
                """Set the global DI container instance."""
         | 
| 855 888 | 
             
                global _global_container
         | 
| 856 889 | 
             
                with _global_lock:
         | 
| 857 | 
            -
                    _global_container = container
         | 
| 890 | 
            +
                    _global_container = container
         |