claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +50 -2
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +271 -268
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +204 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +20 -23
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +581 -280
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -15
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -8,78 +8,97 @@ WHY configuration module:
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
import os
|
|
11
|
-
from typing import List, Optional
|
|
12
11
|
from dataclasses import dataclass, field
|
|
12
|
+
from typing import List, Optional
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@dataclass
|
|
16
16
|
class EventBusConfig:
|
|
17
17
|
"""Configuration for EventBus service.
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
All settings can be overridden via environment variables.
|
|
20
20
|
"""
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
# Enable/disable the EventBus
|
|
23
23
|
enabled: bool = field(
|
|
24
|
-
default_factory=lambda: os.environ.get(
|
|
24
|
+
default_factory=lambda: os.environ.get(
|
|
25
|
+
"CLAUDE_MPM_EVENTBUS_ENABLED", "true"
|
|
26
|
+
).lower()
|
|
27
|
+
== "true"
|
|
25
28
|
)
|
|
26
|
-
|
|
29
|
+
|
|
27
30
|
# Debug logging
|
|
28
31
|
debug: bool = field(
|
|
29
|
-
default_factory=lambda: os.environ.get(
|
|
32
|
+
default_factory=lambda: os.environ.get(
|
|
33
|
+
"CLAUDE_MPM_EVENTBUS_DEBUG", "false"
|
|
34
|
+
).lower()
|
|
35
|
+
== "true"
|
|
30
36
|
)
|
|
31
|
-
|
|
37
|
+
|
|
32
38
|
# Event history settings
|
|
33
39
|
max_history_size: int = field(
|
|
34
|
-
default_factory=lambda: int(
|
|
40
|
+
default_factory=lambda: int(
|
|
41
|
+
os.environ.get("CLAUDE_MPM_EVENTBUS_HISTORY_SIZE", "100")
|
|
42
|
+
)
|
|
35
43
|
)
|
|
36
|
-
|
|
44
|
+
|
|
37
45
|
# Event filters (comma-separated list)
|
|
38
46
|
event_filters: List[str] = field(
|
|
39
47
|
default_factory=lambda: [
|
|
40
|
-
f.strip()
|
|
48
|
+
f.strip()
|
|
49
|
+
for f in os.environ.get("CLAUDE_MPM_EVENTBUS_FILTERS", "").split(",")
|
|
41
50
|
if f.strip()
|
|
42
51
|
]
|
|
43
52
|
)
|
|
44
|
-
|
|
53
|
+
|
|
45
54
|
# Relay configuration
|
|
46
55
|
relay_enabled: bool = field(
|
|
47
|
-
default_factory=lambda: os.environ.get(
|
|
56
|
+
default_factory=lambda: os.environ.get(
|
|
57
|
+
"CLAUDE_MPM_RELAY_ENABLED", "true"
|
|
58
|
+
).lower()
|
|
59
|
+
== "true"
|
|
48
60
|
)
|
|
49
|
-
|
|
61
|
+
|
|
50
62
|
relay_port: int = field(
|
|
51
63
|
default_factory=lambda: int(os.environ.get("CLAUDE_MPM_SOCKETIO_PORT", "8765"))
|
|
52
64
|
)
|
|
53
|
-
|
|
65
|
+
|
|
54
66
|
relay_debug: bool = field(
|
|
55
|
-
default_factory=lambda: os.environ.get(
|
|
67
|
+
default_factory=lambda: os.environ.get(
|
|
68
|
+
"CLAUDE_MPM_RELAY_DEBUG", "false"
|
|
69
|
+
).lower()
|
|
70
|
+
== "true"
|
|
56
71
|
)
|
|
57
|
-
|
|
72
|
+
|
|
58
73
|
# Connection settings
|
|
59
74
|
relay_max_retries: int = field(
|
|
60
75
|
default_factory=lambda: int(os.environ.get("CLAUDE_MPM_RELAY_MAX_RETRIES", "3"))
|
|
61
76
|
)
|
|
62
|
-
|
|
77
|
+
|
|
63
78
|
relay_retry_delay: float = field(
|
|
64
|
-
default_factory=lambda: float(
|
|
79
|
+
default_factory=lambda: float(
|
|
80
|
+
os.environ.get("CLAUDE_MPM_RELAY_RETRY_DELAY", "0.5")
|
|
81
|
+
)
|
|
65
82
|
)
|
|
66
|
-
|
|
83
|
+
|
|
67
84
|
relay_connection_cooldown: float = field(
|
|
68
|
-
default_factory=lambda: float(
|
|
85
|
+
default_factory=lambda: float(
|
|
86
|
+
os.environ.get("CLAUDE_MPM_RELAY_CONNECTION_COOLDOWN", "5.0")
|
|
87
|
+
)
|
|
69
88
|
)
|
|
70
|
-
|
|
89
|
+
|
|
71
90
|
@classmethod
|
|
72
91
|
def from_env(cls) -> "EventBusConfig":
|
|
73
92
|
"""Create configuration from environment variables.
|
|
74
|
-
|
|
93
|
+
|
|
75
94
|
Returns:
|
|
76
95
|
EventBusConfig: Configuration instance
|
|
77
96
|
"""
|
|
78
97
|
return cls()
|
|
79
|
-
|
|
98
|
+
|
|
80
99
|
def to_dict(self) -> dict:
|
|
81
100
|
"""Convert configuration to dictionary.
|
|
82
|
-
|
|
101
|
+
|
|
83
102
|
Returns:
|
|
84
103
|
dict: Configuration as dictionary
|
|
85
104
|
"""
|
|
@@ -93,12 +112,12 @@ class EventBusConfig:
|
|
|
93
112
|
"relay_debug": self.relay_debug,
|
|
94
113
|
"relay_max_retries": self.relay_max_retries,
|
|
95
114
|
"relay_retry_delay": self.relay_retry_delay,
|
|
96
|
-
"relay_connection_cooldown": self.relay_connection_cooldown
|
|
115
|
+
"relay_connection_cooldown": self.relay_connection_cooldown,
|
|
97
116
|
}
|
|
98
|
-
|
|
117
|
+
|
|
99
118
|
def apply_to_eventbus(self, event_bus) -> None:
|
|
100
119
|
"""Apply configuration to an EventBus instance.
|
|
101
|
-
|
|
120
|
+
|
|
102
121
|
Args:
|
|
103
122
|
event_bus: EventBus instance to configure
|
|
104
123
|
"""
|
|
@@ -106,18 +125,18 @@ class EventBusConfig:
|
|
|
106
125
|
event_bus.disable()
|
|
107
126
|
else:
|
|
108
127
|
event_bus.enable()
|
|
109
|
-
|
|
128
|
+
|
|
110
129
|
event_bus.set_debug(self.debug)
|
|
111
130
|
event_bus._max_history_size = self.max_history_size
|
|
112
|
-
|
|
131
|
+
|
|
113
132
|
# Apply filters
|
|
114
133
|
event_bus.clear_filters()
|
|
115
134
|
for filter_pattern in self.event_filters:
|
|
116
135
|
event_bus.add_filter(filter_pattern)
|
|
117
|
-
|
|
136
|
+
|
|
118
137
|
def apply_to_relay(self, relay) -> None:
|
|
119
138
|
"""Apply configuration to a SocketIORelay instance.
|
|
120
|
-
|
|
139
|
+
|
|
121
140
|
Args:
|
|
122
141
|
relay: SocketIORelay instance to configure
|
|
123
142
|
"""
|
|
@@ -125,7 +144,7 @@ class EventBusConfig:
|
|
|
125
144
|
relay.disable()
|
|
126
145
|
else:
|
|
127
146
|
relay.enable()
|
|
128
|
-
|
|
147
|
+
|
|
129
148
|
relay.port = self.relay_port
|
|
130
149
|
relay.debug = self.relay_debug
|
|
131
150
|
relay.max_retries = self.relay_max_retries
|
|
@@ -139,7 +158,7 @@ _config: Optional[EventBusConfig] = None
|
|
|
139
158
|
|
|
140
159
|
def get_config() -> EventBusConfig:
|
|
141
160
|
"""Get the global EventBus configuration.
|
|
142
|
-
|
|
161
|
+
|
|
143
162
|
Returns:
|
|
144
163
|
EventBusConfig: Configuration instance
|
|
145
164
|
"""
|
|
@@ -151,7 +170,7 @@ def get_config() -> EventBusConfig:
|
|
|
151
170
|
|
|
152
171
|
def set_config(config: EventBusConfig) -> None:
|
|
153
172
|
"""Set the global EventBus configuration.
|
|
154
|
-
|
|
173
|
+
|
|
155
174
|
Args:
|
|
156
175
|
config: Configuration to set
|
|
157
176
|
"""
|
|
@@ -162,4 +181,4 @@ def set_config(config: EventBusConfig) -> None:
|
|
|
162
181
|
def reset_config() -> None:
|
|
163
182
|
"""Reset configuration to defaults from environment."""
|
|
164
183
|
global _config
|
|
165
|
-
_config = EventBusConfig.from_env()
|
|
184
|
+
_config = EventBusConfig.from_env()
|
|
@@ -13,6 +13,7 @@ import logging
|
|
|
13
13
|
import threading
|
|
14
14
|
from datetime import datetime
|
|
15
15
|
from typing import Any, Callable, Dict, List, Optional, Set
|
|
16
|
+
|
|
16
17
|
from pyee.asyncio import AsyncIOEventEmitter
|
|
17
18
|
|
|
18
19
|
# Configure logger
|
|
@@ -21,17 +22,17 @@ logger = logging.getLogger(__name__)
|
|
|
21
22
|
|
|
22
23
|
class EventBus:
|
|
23
24
|
"""Singleton Event Bus for decoupled event handling.
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
WHY singleton pattern:
|
|
26
27
|
- Ensures single point of event coordination
|
|
27
28
|
- Prevents duplicate event processing
|
|
28
29
|
- Simplifies configuration and management
|
|
29
30
|
- Thread-safe initialization with proper locking
|
|
30
31
|
"""
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
_instance: Optional["EventBus"] = None
|
|
33
34
|
_lock = threading.Lock()
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
def __new__(cls) -> "EventBus":
|
|
36
37
|
"""Ensure singleton instance creation."""
|
|
37
38
|
if cls._instance is None:
|
|
@@ -39,13 +40,13 @@ class EventBus:
|
|
|
39
40
|
if cls._instance is None:
|
|
40
41
|
cls._instance = super().__new__(cls)
|
|
41
42
|
return cls._instance
|
|
42
|
-
|
|
43
|
+
|
|
43
44
|
def __init__(self):
|
|
44
45
|
"""Initialize the event bus once."""
|
|
45
46
|
# Only initialize once
|
|
46
47
|
if hasattr(self, "_initialized"):
|
|
47
48
|
return
|
|
48
|
-
|
|
49
|
+
|
|
49
50
|
self._initialized = True
|
|
50
51
|
self._emitter = AsyncIOEventEmitter()
|
|
51
52
|
self._enabled = True
|
|
@@ -54,38 +55,38 @@ class EventBus:
|
|
|
54
55
|
"events_published": 0,
|
|
55
56
|
"events_filtered": 0,
|
|
56
57
|
"events_failed": 0,
|
|
57
|
-
"last_event_time": None
|
|
58
|
+
"last_event_time": None,
|
|
58
59
|
}
|
|
59
60
|
self._debug = False
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
# Event history for debugging (limited size)
|
|
62
63
|
self._event_history: List[Dict[str, Any]] = []
|
|
63
64
|
self._max_history_size = 100
|
|
64
|
-
|
|
65
|
+
|
|
65
66
|
logger.info("EventBus initialized")
|
|
66
|
-
|
|
67
|
+
|
|
67
68
|
@classmethod
|
|
68
69
|
def get_instance(cls) -> "EventBus":
|
|
69
70
|
"""Get the singleton EventBus instance.
|
|
70
|
-
|
|
71
|
+
|
|
71
72
|
Returns:
|
|
72
73
|
EventBus: The singleton instance
|
|
73
74
|
"""
|
|
74
75
|
return cls()
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
def enable(self) -> None:
|
|
77
78
|
"""Enable event bus processing."""
|
|
78
79
|
self._enabled = True
|
|
79
80
|
logger.info("EventBus enabled")
|
|
80
|
-
|
|
81
|
+
|
|
81
82
|
def disable(self) -> None:
|
|
82
83
|
"""Disable event bus processing (for testing or maintenance)."""
|
|
83
84
|
self._enabled = False
|
|
84
85
|
logger.info("EventBus disabled")
|
|
85
|
-
|
|
86
|
+
|
|
86
87
|
def set_debug(self, debug: bool) -> None:
|
|
87
88
|
"""Enable or disable debug logging.
|
|
88
|
-
|
|
89
|
+
|
|
89
90
|
Args:
|
|
90
91
|
debug: Whether to enable debug logging
|
|
91
92
|
"""
|
|
@@ -94,46 +95,46 @@ class EventBus:
|
|
|
94
95
|
logger.setLevel(logging.DEBUG)
|
|
95
96
|
else:
|
|
96
97
|
logger.setLevel(logging.INFO)
|
|
97
|
-
|
|
98
|
+
|
|
98
99
|
def add_filter(self, pattern: str) -> None:
|
|
99
100
|
"""Add an event filter pattern.
|
|
100
|
-
|
|
101
|
+
|
|
101
102
|
Only events matching filter patterns will be processed.
|
|
102
103
|
Use wildcards: 'hook.*' matches all hook events.
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
Args:
|
|
105
106
|
pattern: Event name pattern to allow
|
|
106
107
|
"""
|
|
107
108
|
self._event_filters.add(pattern)
|
|
108
109
|
logger.debug(f"Added event filter: {pattern}")
|
|
109
|
-
|
|
110
|
+
|
|
110
111
|
def remove_filter(self, pattern: str) -> None:
|
|
111
112
|
"""Remove an event filter pattern.
|
|
112
|
-
|
|
113
|
+
|
|
113
114
|
Args:
|
|
114
115
|
pattern: Event name pattern to remove
|
|
115
116
|
"""
|
|
116
117
|
self._event_filters.discard(pattern)
|
|
117
118
|
logger.debug(f"Removed event filter: {pattern}")
|
|
118
|
-
|
|
119
|
+
|
|
119
120
|
def clear_filters(self) -> None:
|
|
120
121
|
"""Clear all event filters (allow all events)."""
|
|
121
122
|
self._event_filters.clear()
|
|
122
123
|
logger.debug("Cleared all event filters")
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
def _should_process_event(self, event_type: str) -> bool:
|
|
125
126
|
"""Check if an event should be processed based on filters.
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
Args:
|
|
128
129
|
event_type: The event type to check
|
|
129
|
-
|
|
130
|
+
|
|
130
131
|
Returns:
|
|
131
132
|
bool: True if event should be processed
|
|
132
133
|
"""
|
|
133
134
|
# If no filters, process all events
|
|
134
135
|
if not self._event_filters:
|
|
135
136
|
return True
|
|
136
|
-
|
|
137
|
+
|
|
137
138
|
# Check if event matches any filter
|
|
138
139
|
for filter_pattern in self._event_filters:
|
|
139
140
|
if filter_pattern.endswith("*"):
|
|
@@ -144,19 +145,19 @@ class EventBus:
|
|
|
144
145
|
elif event_type == filter_pattern:
|
|
145
146
|
# Exact match
|
|
146
147
|
return True
|
|
147
|
-
|
|
148
|
+
|
|
148
149
|
return False
|
|
149
|
-
|
|
150
|
+
|
|
150
151
|
def publish(self, event_type: str, data: Any) -> bool:
|
|
151
152
|
"""Publish an event synchronously (for use from sync contexts like hooks).
|
|
152
|
-
|
|
153
|
+
|
|
153
154
|
This method is thread-safe and can be called from any thread.
|
|
154
155
|
Events are dispatched asynchronously to handlers.
|
|
155
|
-
|
|
156
|
+
|
|
156
157
|
Args:
|
|
157
158
|
event_type: The event type (e.g., 'hook.pre_tool')
|
|
158
159
|
data: The event data
|
|
159
|
-
|
|
160
|
+
|
|
160
161
|
Returns:
|
|
161
162
|
bool: True if event was published, False if filtered or disabled
|
|
162
163
|
"""
|
|
@@ -164,23 +165,23 @@ class EventBus:
|
|
|
164
165
|
if self._debug:
|
|
165
166
|
logger.debug(f"EventBus disabled, dropping event: {event_type}")
|
|
166
167
|
return False
|
|
167
|
-
|
|
168
|
+
|
|
168
169
|
# Check filters
|
|
169
170
|
if not self._should_process_event(event_type):
|
|
170
171
|
self._stats["events_filtered"] += 1
|
|
171
172
|
if self._debug:
|
|
172
173
|
logger.debug(f"Event filtered out: {event_type}")
|
|
173
174
|
return False
|
|
174
|
-
|
|
175
|
+
|
|
175
176
|
try:
|
|
176
177
|
# Record event in history
|
|
177
178
|
self._record_event(event_type, data)
|
|
178
|
-
|
|
179
|
+
|
|
179
180
|
# Emit event to regular handlers (pyee handles thread safety)
|
|
180
181
|
self._emitter.emit(event_type, data)
|
|
181
|
-
|
|
182
|
+
|
|
182
183
|
# Also emit to wildcard handlers
|
|
183
|
-
if hasattr(self,
|
|
184
|
+
if hasattr(self, "_wildcard_handlers"):
|
|
184
185
|
for prefix, handlers in self._wildcard_handlers.items():
|
|
185
186
|
if event_type.startswith(prefix):
|
|
186
187
|
for handler in handlers:
|
|
@@ -191,9 +192,13 @@ class EventBus:
|
|
|
191
192
|
try:
|
|
192
193
|
loop = asyncio.get_event_loop()
|
|
193
194
|
if loop.is_running():
|
|
194
|
-
asyncio.create_task(
|
|
195
|
+
asyncio.create_task(
|
|
196
|
+
handler(event_type, data)
|
|
197
|
+
)
|
|
195
198
|
else:
|
|
196
|
-
loop.run_until_complete(
|
|
199
|
+
loop.run_until_complete(
|
|
200
|
+
handler(event_type, data)
|
|
201
|
+
)
|
|
197
202
|
except RuntimeError:
|
|
198
203
|
# No event loop, skip async handler
|
|
199
204
|
pass
|
|
@@ -202,83 +207,83 @@ class EventBus:
|
|
|
202
207
|
except Exception as e:
|
|
203
208
|
if self._debug:
|
|
204
209
|
logger.debug(f"Wildcard handler error: {e}")
|
|
205
|
-
|
|
210
|
+
|
|
206
211
|
# Update stats
|
|
207
212
|
self._stats["events_published"] += 1
|
|
208
213
|
self._stats["last_event_time"] = datetime.now().isoformat()
|
|
209
|
-
|
|
214
|
+
|
|
210
215
|
if self._debug:
|
|
211
216
|
logger.debug(f"Published event: {event_type}")
|
|
212
|
-
|
|
217
|
+
|
|
213
218
|
return True
|
|
214
|
-
|
|
219
|
+
|
|
215
220
|
except Exception as e:
|
|
216
221
|
self._stats["events_failed"] += 1
|
|
217
222
|
logger.error(f"Failed to publish event {event_type}: {e}")
|
|
218
223
|
return False
|
|
219
|
-
|
|
224
|
+
|
|
220
225
|
async def publish_async(self, event_type: str, data: Any) -> bool:
|
|
221
226
|
"""Publish an event from an async context.
|
|
222
|
-
|
|
227
|
+
|
|
223
228
|
Args:
|
|
224
229
|
event_type: The event type
|
|
225
230
|
data: The event data
|
|
226
|
-
|
|
231
|
+
|
|
227
232
|
Returns:
|
|
228
233
|
bool: True if event was published
|
|
229
234
|
"""
|
|
230
235
|
# Just delegate to sync publish (pyee handles both)
|
|
231
236
|
return self.publish(event_type, data)
|
|
232
|
-
|
|
237
|
+
|
|
233
238
|
def on(self, event_type: str, handler: Callable) -> None:
|
|
234
239
|
"""Register an event handler.
|
|
235
|
-
|
|
240
|
+
|
|
236
241
|
The handler can be sync or async. For async handlers,
|
|
237
242
|
they will be scheduled on the event loop.
|
|
238
|
-
|
|
243
|
+
|
|
239
244
|
Args:
|
|
240
245
|
event_type: The event type to listen for (supports wildcards)
|
|
241
246
|
handler: The handler function
|
|
242
247
|
"""
|
|
243
248
|
if event_type.endswith("*"):
|
|
244
249
|
# Store wildcard handlers separately
|
|
245
|
-
if not hasattr(self,
|
|
250
|
+
if not hasattr(self, "_wildcard_handlers"):
|
|
246
251
|
self._wildcard_handlers = {}
|
|
247
|
-
|
|
252
|
+
|
|
248
253
|
prefix = event_type[:-1]
|
|
249
254
|
if prefix not in self._wildcard_handlers:
|
|
250
255
|
self._wildcard_handlers[prefix] = []
|
|
251
256
|
self._wildcard_handlers[prefix].append(handler)
|
|
252
|
-
|
|
257
|
+
|
|
253
258
|
logger.debug(f"Registered wildcard handler for: {event_type}")
|
|
254
259
|
else:
|
|
255
260
|
# Regular event registration
|
|
256
261
|
self._emitter.on(event_type, handler)
|
|
257
262
|
logger.debug(f"Registered handler for: {event_type}")
|
|
258
|
-
|
|
263
|
+
|
|
259
264
|
def once(self, event_type: str, handler: Callable) -> None:
|
|
260
265
|
"""Register a one-time event handler.
|
|
261
|
-
|
|
266
|
+
|
|
262
267
|
Args:
|
|
263
268
|
event_type: The event type to listen for
|
|
264
269
|
handler: The handler function
|
|
265
270
|
"""
|
|
266
271
|
self._emitter.once(event_type, handler)
|
|
267
272
|
logger.debug(f"Registered one-time handler for: {event_type}")
|
|
268
|
-
|
|
273
|
+
|
|
269
274
|
def remove_listener(self, event_type: str, handler: Callable) -> None:
|
|
270
275
|
"""Remove an event handler.
|
|
271
|
-
|
|
276
|
+
|
|
272
277
|
Args:
|
|
273
278
|
event_type: The event type
|
|
274
279
|
handler: The handler to remove
|
|
275
280
|
"""
|
|
276
281
|
self._emitter.remove_listener(event_type, handler)
|
|
277
282
|
logger.debug(f"Removed handler for: {event_type}")
|
|
278
|
-
|
|
283
|
+
|
|
279
284
|
def remove_all_listeners(self, event_type: Optional[str] = None) -> None:
|
|
280
285
|
"""Remove all listeners for an event type, or all listeners.
|
|
281
|
-
|
|
286
|
+
|
|
282
287
|
Args:
|
|
283
288
|
event_type: Optional event type. If None, removes all listeners.
|
|
284
289
|
"""
|
|
@@ -288,10 +293,10 @@ class EventBus:
|
|
|
288
293
|
else:
|
|
289
294
|
self._emitter.remove_all_listeners()
|
|
290
295
|
logger.debug("Removed all event handlers")
|
|
291
|
-
|
|
296
|
+
|
|
292
297
|
def _record_event(self, event_type: str, data: Any) -> None:
|
|
293
298
|
"""Record event in history for debugging.
|
|
294
|
-
|
|
299
|
+
|
|
295
300
|
Args:
|
|
296
301
|
event_type: The event type
|
|
297
302
|
data: The event data
|
|
@@ -299,18 +304,18 @@ class EventBus:
|
|
|
299
304
|
event_record = {
|
|
300
305
|
"timestamp": datetime.now().isoformat(),
|
|
301
306
|
"type": event_type,
|
|
302
|
-
"data": data
|
|
307
|
+
"data": data,
|
|
303
308
|
}
|
|
304
|
-
|
|
309
|
+
|
|
305
310
|
self._event_history.append(event_record)
|
|
306
|
-
|
|
311
|
+
|
|
307
312
|
# Trim history if too large
|
|
308
313
|
if len(self._event_history) > self._max_history_size:
|
|
309
|
-
self._event_history = self._event_history[-self._max_history_size:]
|
|
310
|
-
|
|
314
|
+
self._event_history = self._event_history[-self._max_history_size :]
|
|
315
|
+
|
|
311
316
|
def get_stats(self) -> Dict[str, Any]:
|
|
312
317
|
"""Get event bus statistics.
|
|
313
|
-
|
|
318
|
+
|
|
314
319
|
Returns:
|
|
315
320
|
dict: Statistics about event processing
|
|
316
321
|
"""
|
|
@@ -319,31 +324,31 @@ class EventBus:
|
|
|
319
324
|
"enabled": self._enabled,
|
|
320
325
|
"filters_active": len(self._event_filters) > 0,
|
|
321
326
|
"filter_count": len(self._event_filters),
|
|
322
|
-
"history_size": len(self._event_history)
|
|
327
|
+
"history_size": len(self._event_history),
|
|
323
328
|
}
|
|
324
|
-
|
|
329
|
+
|
|
325
330
|
def get_recent_events(self, limit: int = 10) -> List[Dict[str, Any]]:
|
|
326
331
|
"""Get recent events from history.
|
|
327
|
-
|
|
332
|
+
|
|
328
333
|
Args:
|
|
329
334
|
limit: Maximum number of events to return
|
|
330
|
-
|
|
335
|
+
|
|
331
336
|
Returns:
|
|
332
337
|
list: Recent events
|
|
333
338
|
"""
|
|
334
339
|
return self._event_history[-limit:]
|
|
335
|
-
|
|
340
|
+
|
|
336
341
|
def clear_history(self) -> None:
|
|
337
342
|
"""Clear the event history."""
|
|
338
343
|
self._event_history.clear()
|
|
339
344
|
logger.debug("Cleared event history")
|
|
340
|
-
|
|
345
|
+
|
|
341
346
|
def reset_stats(self) -> None:
|
|
342
347
|
"""Reset event statistics."""
|
|
343
348
|
self._stats = {
|
|
344
349
|
"events_published": 0,
|
|
345
350
|
"events_filtered": 0,
|
|
346
351
|
"events_failed": 0,
|
|
347
|
-
"last_event_time": None
|
|
352
|
+
"last_event_time": None,
|
|
348
353
|
}
|
|
349
|
-
logger.debug("Reset event statistics")
|
|
354
|
+
logger.debug("Reset event statistics")
|