claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +2 -2
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +140 -905
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +330 -86
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +363 -220
- claude_mpm/cli/parser.py +24 -1156
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +124 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/built/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/built/dashboard.js +2 -0
- claude_mpm/dashboard/static/built/socket-client.js +2 -0
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +133 -53
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +233 -199
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +30 -13
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +575 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +166 -64
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +185 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +19 -533
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
- claude_mpm-4.0.4.dist-info/RECORD +417 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
| @@ -0,0 +1,164 @@ | |
| 1 | 
            +
            /**
         | 
| 2 | 
            +
             * Browser Extension Error Handler
         | 
| 3 | 
            +
             * 
         | 
| 4 | 
            +
             * WHY: Browser extensions (like password managers, ad blockers, etc.) often inject
         | 
| 5 | 
            +
             * scripts that use Chrome's message passing API. When these extensions have bugs
         | 
| 6 | 
            +
             * or async handlers that don't properly respond, they generate console errors.
         | 
| 7 | 
            +
             * 
         | 
| 8 | 
            +
             * This module prevents those external errors from affecting our dashboard and
         | 
| 9 | 
            +
             * provides clean error handling for known browser extension issues.
         | 
| 10 | 
            +
             * 
         | 
| 11 | 
            +
             * DESIGN DECISION: Rather than trying to fix third-party extension bugs, we:
         | 
| 12 | 
            +
             * 1. Detect and suppress known harmless extension errors
         | 
| 13 | 
            +
             * 2. Log them separately for debugging if needed
         | 
| 14 | 
            +
             * 3. Ensure our dashboard remains functional regardless of extension conflicts
         | 
| 15 | 
            +
             */
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            class ExtensionErrorHandler {
         | 
| 18 | 
            +
                constructor() {
         | 
| 19 | 
            +
                    this.extensionErrors = [];
         | 
| 20 | 
            +
                    this.suppressedPatterns = [
         | 
| 21 | 
            +
                        // Chrome extension message passing error
         | 
| 22 | 
            +
                        /listener indicated an asynchronous response.*message channel closed/i,
         | 
| 23 | 
            +
                        // Other common extension errors
         | 
| 24 | 
            +
                        /Extension context invalidated/i,
         | 
| 25 | 
            +
                        /Unchecked runtime\.lastError/i,
         | 
| 26 | 
            +
                        /Cannot access contents of url.*Extension/i,
         | 
| 27 | 
            +
                        /Blocked a frame with origin.*from accessing a cross-origin frame/i
         | 
| 28 | 
            +
                    ];
         | 
| 29 | 
            +
                    
         | 
| 30 | 
            +
                    this.setupErrorHandling();
         | 
| 31 | 
            +
                }
         | 
| 32 | 
            +
                
         | 
| 33 | 
            +
                /**
         | 
| 34 | 
            +
                 * Set up global error handling to catch and suppress extension errors
         | 
| 35 | 
            +
                 */
         | 
| 36 | 
            +
                setupErrorHandling() {
         | 
| 37 | 
            +
                    // Store original console.error
         | 
| 38 | 
            +
                    const originalConsoleError = console.error;
         | 
| 39 | 
            +
                    
         | 
| 40 | 
            +
                    // Override console.error to filter extension errors
         | 
| 41 | 
            +
                    console.error = (...args) => {
         | 
| 42 | 
            +
                        const errorString = args.join(' ');
         | 
| 43 | 
            +
                        
         | 
| 44 | 
            +
                        // Check if this is a known extension error
         | 
| 45 | 
            +
                        if (this.isExtensionError(errorString)) {
         | 
| 46 | 
            +
                            // Log to our internal list for debugging
         | 
| 47 | 
            +
                            this.extensionErrors.push({
         | 
| 48 | 
            +
                                timestamp: new Date().toISOString(),
         | 
| 49 | 
            +
                                error: errorString,
         | 
| 50 | 
            +
                                suppressed: true
         | 
| 51 | 
            +
                            });
         | 
| 52 | 
            +
                            
         | 
| 53 | 
            +
                            // Optionally log with a prefix if debug mode is enabled
         | 
| 54 | 
            +
                            if (window.DEBUG_EXTENSION_ERRORS) {
         | 
| 55 | 
            +
                                originalConsoleError.call(console, '[SUPPRESSED EXTENSION ERROR]:', ...args);
         | 
| 56 | 
            +
                            }
         | 
| 57 | 
            +
                            
         | 
| 58 | 
            +
                            // Don't propagate the error
         | 
| 59 | 
            +
                            return;
         | 
| 60 | 
            +
                        }
         | 
| 61 | 
            +
                        
         | 
| 62 | 
            +
                        // Pass through non-extension errors
         | 
| 63 | 
            +
                        originalConsoleError.call(console, ...args);
         | 
| 64 | 
            +
                    };
         | 
| 65 | 
            +
                    
         | 
| 66 | 
            +
                    // Handle uncaught promise rejections that might come from extensions
         | 
| 67 | 
            +
                    window.addEventListener('unhandledrejection', (event) => {
         | 
| 68 | 
            +
                        const errorString = event.reason?.toString() || '';
         | 
| 69 | 
            +
                        
         | 
| 70 | 
            +
                        if (this.isExtensionError(errorString)) {
         | 
| 71 | 
            +
                            // Prevent the default error handling
         | 
| 72 | 
            +
                            event.preventDefault();
         | 
| 73 | 
            +
                            
         | 
| 74 | 
            +
                            this.extensionErrors.push({
         | 
| 75 | 
            +
                                timestamp: new Date().toISOString(),
         | 
| 76 | 
            +
                                error: errorString,
         | 
| 77 | 
            +
                                type: 'unhandled_rejection',
         | 
| 78 | 
            +
                                suppressed: true
         | 
| 79 | 
            +
                            });
         | 
| 80 | 
            +
                            
         | 
| 81 | 
            +
                            if (window.DEBUG_EXTENSION_ERRORS) {
         | 
| 82 | 
            +
                                console.warn('[SUPPRESSED EXTENSION REJECTION]:', event.reason);
         | 
| 83 | 
            +
                            }
         | 
| 84 | 
            +
                        }
         | 
| 85 | 
            +
                    });
         | 
| 86 | 
            +
                    
         | 
| 87 | 
            +
                    // Add a global message event listener with proper error handling
         | 
| 88 | 
            +
                    // This prevents our app from being affected by misbehaving extensions
         | 
| 89 | 
            +
                    window.addEventListener('message', (event) => {
         | 
| 90 | 
            +
                        // Only process messages from our own origin
         | 
| 91 | 
            +
                        if (event.origin !== window.location.origin) {
         | 
| 92 | 
            +
                            return;
         | 
| 93 | 
            +
                        }
         | 
| 94 | 
            +
                        
         | 
| 95 | 
            +
                        // Add timeout protection for any async operations
         | 
| 96 | 
            +
                        if (event.data && event.data.requiresResponse) {
         | 
| 97 | 
            +
                            const timeoutId = setTimeout(() => {
         | 
| 98 | 
            +
                                console.warn('Message handler timeout - no response sent');
         | 
| 99 | 
            +
                            }, 5000);
         | 
| 100 | 
            +
                            
         | 
| 101 | 
            +
                            // Clear timeout when response is sent
         | 
| 102 | 
            +
                            if (event.ports && event.ports[0]) {
         | 
| 103 | 
            +
                                const originalPostMessage = event.ports[0].postMessage;
         | 
| 104 | 
            +
                                event.ports[0].postMessage = function(...args) {
         | 
| 105 | 
            +
                                    clearTimeout(timeoutId);
         | 
| 106 | 
            +
                                    return originalPostMessage.apply(this, args);
         | 
| 107 | 
            +
                                };
         | 
| 108 | 
            +
                            }
         | 
| 109 | 
            +
                        }
         | 
| 110 | 
            +
                    });
         | 
| 111 | 
            +
                }
         | 
| 112 | 
            +
                
         | 
| 113 | 
            +
                /**
         | 
| 114 | 
            +
                 * Check if an error string matches known extension error patterns
         | 
| 115 | 
            +
                 * @param {string} errorString - The error message to check
         | 
| 116 | 
            +
                 * @returns {boolean} - True if this is a known extension error
         | 
| 117 | 
            +
                 */
         | 
| 118 | 
            +
                isExtensionError(errorString) {
         | 
| 119 | 
            +
                    return this.suppressedPatterns.some(pattern => pattern.test(errorString));
         | 
| 120 | 
            +
                }
         | 
| 121 | 
            +
                
         | 
| 122 | 
            +
                /**
         | 
| 123 | 
            +
                 * Get suppressed extension errors for debugging
         | 
| 124 | 
            +
                 * @returns {Array} - List of suppressed errors
         | 
| 125 | 
            +
                 */
         | 
| 126 | 
            +
                getSuppressedErrors() {
         | 
| 127 | 
            +
                    return this.extensionErrors;
         | 
| 128 | 
            +
                }
         | 
| 129 | 
            +
                
         | 
| 130 | 
            +
                /**
         | 
| 131 | 
            +
                 * Clear the suppressed errors list
         | 
| 132 | 
            +
                 */
         | 
| 133 | 
            +
                clearSuppressedErrors() {
         | 
| 134 | 
            +
                    this.extensionErrors = [];
         | 
| 135 | 
            +
                }
         | 
| 136 | 
            +
                
         | 
| 137 | 
            +
                /**
         | 
| 138 | 
            +
                 * Enable or disable debug logging of extension errors
         | 
| 139 | 
            +
                 * @param {boolean} enabled - Whether to enable debug logging
         | 
| 140 | 
            +
                 */
         | 
| 141 | 
            +
                setDebugMode(enabled) {
         | 
| 142 | 
            +
                    window.DEBUG_EXTENSION_ERRORS = enabled;
         | 
| 143 | 
            +
                    
         | 
| 144 | 
            +
                    if (enabled) {
         | 
| 145 | 
            +
                        console.log('Extension error debug mode enabled. Suppressed errors will be logged with [SUPPRESSED] prefix.');
         | 
| 146 | 
            +
                        console.log('Current suppressed errors:', this.getSuppressedErrors());
         | 
| 147 | 
            +
                    } else {
         | 
| 148 | 
            +
                        console.log('Extension error debug mode disabled. Extension errors will be silently suppressed.');
         | 
| 149 | 
            +
                    }
         | 
| 150 | 
            +
                }
         | 
| 151 | 
            +
            }
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            // Create and export singleton instance
         | 
| 154 | 
            +
            const extensionErrorHandler = new ExtensionErrorHandler();
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            // Add to window for debugging access
         | 
| 157 | 
            +
            window.extensionErrorHandler = extensionErrorHandler;
         | 
| 158 | 
            +
             | 
| 159 | 
            +
            // Export for ES6 modules
         | 
| 160 | 
            +
            export { ExtensionErrorHandler, extensionErrorHandler };
         | 
| 161 | 
            +
            export default extensionErrorHandler;
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            // Log initialization
         | 
| 164 | 
            +
            console.log('Extension error handler initialized. Use window.extensionErrorHandler.setDebugMode(true) to see suppressed errors.');
         | 
| @@ -3,6 +3,9 @@ | |
| 3 3 | 
             
             * Handles WebSocket connections and event processing
         | 
| 4 4 | 
             
             */
         | 
| 5 5 |  | 
| 6 | 
            +
            // Access the global io from window object in ES6 module context
         | 
| 7 | 
            +
            const io = window.io;
         | 
| 8 | 
            +
             | 
| 6 9 | 
             
            class SocketClient {
         | 
| 7 10 | 
             
                constructor() {
         | 
| 8 11 | 
             
                    this.socket = null;
         | 
| @@ -13,16 +16,16 @@ class SocketClient { | |
| 13 16 | 
             
                        error: [],
         | 
| 14 17 | 
             
                        event: []
         | 
| 15 18 | 
             
                    };
         | 
| 16 | 
            -
             | 
| 19 | 
            +
             | 
| 17 20 | 
             
                    // Connection state
         | 
| 18 21 | 
             
                    this.isConnected = false;
         | 
| 19 22 | 
             
                    this.isConnecting = false;
         | 
| 20 | 
            -
             | 
| 23 | 
            +
             | 
| 21 24 | 
             
                    // Event processing
         | 
| 22 25 | 
             
                    this.events = [];
         | 
| 23 26 | 
             
                    this.sessions = new Map();
         | 
| 24 27 | 
             
                    this.currentSessionId = null;
         | 
| 25 | 
            -
             | 
| 28 | 
            +
             | 
| 26 29 | 
             
                    // Start periodic status check as fallback mechanism
         | 
| 27 30 | 
             
                    this.startStatusCheckFallback();
         | 
| 28 31 | 
             
                }
         | 
| @@ -35,7 +38,7 @@ class SocketClient { | |
| 35 38 | 
             
                    // Store the port for later use
         | 
| 36 39 | 
             
                    this.port = port;
         | 
| 37 40 | 
             
                    const url = `http://localhost:${port}`;
         | 
| 38 | 
            -
             | 
| 41 | 
            +
             | 
| 39 42 | 
             
                    // Prevent multiple simultaneous connections
         | 
| 40 43 | 
             
                    if (this.socket && (this.socket.connected || this.socket.connecting)) {
         | 
| 41 44 | 
             
                        console.log('Already connected or connecting, disconnecting first...');
         | 
| @@ -44,7 +47,7 @@ class SocketClient { | |
| 44 47 | 
             
                        setTimeout(() => this.doConnect(url), 100);
         | 
| 45 48 | 
             
                        return;
         | 
| 46 49 | 
             
                    }
         | 
| 47 | 
            -
             | 
| 50 | 
            +
             | 
| 48 51 | 
             
                    this.doConnect(url);
         | 
| 49 52 | 
             
                }
         | 
| 50 53 |  | 
| @@ -54,9 +57,17 @@ class SocketClient { | |
| 54 57 | 
             
                 */
         | 
| 55 58 | 
             
                doConnect(url) {
         | 
| 56 59 | 
             
                    console.log(`Connecting to Socket.IO server at ${url}`);
         | 
| 60 | 
            +
                    
         | 
| 61 | 
            +
                    // Check if io is available
         | 
| 62 | 
            +
                    if (typeof io === 'undefined') {
         | 
| 63 | 
            +
                        console.error('Socket.IO library not loaded! Make sure socket.io.min.js is loaded before this script.');
         | 
| 64 | 
            +
                        this.notifyConnectionStatus('Socket.IO library not loaded', 'error');
         | 
| 65 | 
            +
                        return;
         | 
| 66 | 
            +
                    }
         | 
| 67 | 
            +
                    
         | 
| 57 68 | 
             
                    this.isConnecting = true;
         | 
| 58 69 | 
             
                    this.notifyConnectionStatus('Connecting...', 'connecting');
         | 
| 59 | 
            -
             | 
| 70 | 
            +
             | 
| 60 71 | 
             
                    this.socket = io(url, {
         | 
| 61 72 | 
             
                        autoConnect: true,
         | 
| 62 73 | 
             
                        reconnection: true,
         | 
| @@ -67,7 +78,7 @@ class SocketClient { | |
| 67 78 | 
             
                        forceNew: true,
         | 
| 68 79 | 
             
                        transports: ['websocket', 'polling']
         | 
| 69 80 | 
             
                    });
         | 
| 70 | 
            -
             | 
| 81 | 
            +
             | 
| 71 82 | 
             
                    this.setupSocketHandlers();
         | 
| 72 83 | 
             
                }
         | 
| 73 84 |  | 
| @@ -80,55 +91,55 @@ class SocketClient { | |
| 80 91 | 
             
                        this.isConnected = true;
         | 
| 81 92 | 
             
                        this.isConnecting = false;
         | 
| 82 93 | 
             
                        this.notifyConnectionStatus('Connected', 'connected');
         | 
| 83 | 
            -
             | 
| 94 | 
            +
             | 
| 84 95 | 
             
                        // Emit connect callback
         | 
| 85 | 
            -
                        this.connectionCallbacks.connect.forEach(callback => | 
| 96 | 
            +
                        this.connectionCallbacks.connect.forEach(callback =>
         | 
| 86 97 | 
             
                            callback(this.socket.id)
         | 
| 87 98 | 
             
                        );
         | 
| 88 | 
            -
             | 
| 99 | 
            +
             | 
| 89 100 | 
             
                        this.requestStatus();
         | 
| 90 101 | 
             
                        // History is now automatically sent by server on connection
         | 
| 91 102 | 
             
                        // No need to explicitly request it
         | 
| 92 103 | 
             
                    });
         | 
| 93 | 
            -
             | 
| 104 | 
            +
             | 
| 94 105 | 
             
                    this.socket.on('disconnect', (reason) => {
         | 
| 95 106 | 
             
                        console.log('Disconnected from server:', reason);
         | 
| 96 107 | 
             
                        this.isConnected = false;
         | 
| 97 108 | 
             
                        this.isConnecting = false;
         | 
| 98 109 | 
             
                        this.notifyConnectionStatus(`Disconnected: ${reason}`, 'disconnected');
         | 
| 99 | 
            -
             | 
| 110 | 
            +
             | 
| 100 111 | 
             
                        // Emit disconnect callback
         | 
| 101 | 
            -
                        this.connectionCallbacks.disconnect.forEach(callback => | 
| 112 | 
            +
                        this.connectionCallbacks.disconnect.forEach(callback =>
         | 
| 102 113 | 
             
                            callback(reason)
         | 
| 103 114 | 
             
                        );
         | 
| 104 115 | 
             
                    });
         | 
| 105 | 
            -
             | 
| 116 | 
            +
             | 
| 106 117 | 
             
                    this.socket.on('connect_error', (error) => {
         | 
| 107 118 | 
             
                        console.error('Connection error:', error);
         | 
| 108 119 | 
             
                        this.isConnecting = false;
         | 
| 109 120 | 
             
                        const errorMsg = error.message || error.description || 'Unknown error';
         | 
| 110 121 | 
             
                        this.notifyConnectionStatus(`Connection Error: ${errorMsg}`, 'disconnected');
         | 
| 111 | 
            -
             | 
| 122 | 
            +
             | 
| 112 123 | 
             
                        // Add error event
         | 
| 113 124 | 
             
                        this.addEvent({
         | 
| 114 125 | 
             
                            type: 'connection.error',
         | 
| 115 126 | 
             
                            timestamp: new Date().toISOString(),
         | 
| 116 127 | 
             
                            data: { error: errorMsg, url: this.socket.io.uri }
         | 
| 117 128 | 
             
                        });
         | 
| 118 | 
            -
             | 
| 129 | 
            +
             | 
| 119 130 | 
             
                        // Emit error callback
         | 
| 120 | 
            -
                        this.connectionCallbacks.error.forEach(callback => | 
| 131 | 
            +
                        this.connectionCallbacks.error.forEach(callback =>
         | 
| 121 132 | 
             
                            callback(errorMsg)
         | 
| 122 133 | 
             
                        );
         | 
| 123 134 | 
             
                    });
         | 
| 124 135 |  | 
| 125 136 | 
             
                    // Primary event handler - this is what the server actually emits
         | 
| 126 137 | 
             
                    this.socket.on('claude_event', (data) => {
         | 
| 127 | 
            -
                        console.log('Received claude_event:', data);
         | 
| 128 | 
            -
             | 
| 138 | 
            +
                        // console.log('Received claude_event:', data);
         | 
| 139 | 
            +
             | 
| 129 140 | 
             
                        // Transform event to match expected format
         | 
| 130 141 | 
             
                        const transformedEvent = this.transformEvent(data);
         | 
| 131 | 
            -
                        console.log('Transformed event:', transformedEvent);
         | 
| 142 | 
            +
                        // console.log('Transformed event:', transformedEvent);
         | 
| 132 143 | 
             
                        this.addEvent(transformedEvent);
         | 
| 133 144 | 
             
                    });
         | 
| 134 145 |  | 
| @@ -310,7 +321,7 @@ class SocketClient { | |
| 310 321 | 
             
                    this.sessions.clear();
         | 
| 311 322 | 
             
                    this.notifyEventUpdate();
         | 
| 312 323 | 
             
                }
         | 
| 313 | 
            -
             | 
| 324 | 
            +
             | 
| 314 325 | 
             
                /**
         | 
| 315 326 | 
             
                 * Clear events and request fresh history from server
         | 
| 316 327 | 
             
                 * @param {Object} options - History request options (same as requestHistory)
         | 
| @@ -329,7 +340,7 @@ class SocketClient { | |
| 329 340 | 
             
                    if (!sessionId) {
         | 
| 330 341 | 
             
                        return this.events;
         | 
| 331 342 | 
             
                    }
         | 
| 332 | 
            -
                    return this.events.filter(event => | 
| 343 | 
            +
                    return this.events.filter(event =>
         | 
| 333 344 | 
             
                        event.data && event.data.session_id === sessionId
         | 
| 334 345 | 
             
                    );
         | 
| 335 346 | 
             
                }
         | 
| @@ -360,10 +371,10 @@ class SocketClient { | |
| 360 371 | 
             
                 */
         | 
| 361 372 | 
             
                notifyConnectionStatus(status, type) {
         | 
| 362 373 | 
             
                    console.log(`SocketClient: Connection status changed to '${status}' (${type})`);
         | 
| 363 | 
            -
             | 
| 374 | 
            +
             | 
| 364 375 | 
             
                    // Direct DOM update - immediate and reliable
         | 
| 365 376 | 
             
                    this.updateConnectionStatusDOM(status, type);
         | 
| 366 | 
            -
             | 
| 377 | 
            +
             | 
| 367 378 | 
             
                    // Also dispatch custom event for other modules
         | 
| 368 379 | 
             
                    document.dispatchEvent(new CustomEvent('socketConnectionStatus', {
         | 
| 369 380 | 
             
                        detail: { status, type }
         | 
| @@ -380,10 +391,10 @@ class SocketClient { | |
| 380 391 | 
             
                    if (statusElement) {
         | 
| 381 392 | 
             
                        // Update the text content while preserving the indicator span
         | 
| 382 393 | 
             
                        statusElement.innerHTML = `<span>●</span> ${status}`;
         | 
| 383 | 
            -
             | 
| 394 | 
            +
             | 
| 384 395 | 
             
                        // Update the CSS class for styling
         | 
| 385 396 | 
             
                        statusElement.className = `status-badge status-${type}`;
         | 
| 386 | 
            -
             | 
| 397 | 
            +
             | 
| 387 398 | 
             
                        console.log(`SocketClient: Direct DOM update - status: '${status}' (${type})`);
         | 
| 388 399 | 
             
                    } else {
         | 
| 389 400 | 
             
                        console.warn('SocketClient: Could not find connection-status element in DOM');
         | 
| @@ -394,10 +405,10 @@ class SocketClient { | |
| 394 405 | 
             
                 * Notify event update
         | 
| 395 406 | 
             
                 */
         | 
| 396 407 | 
             
                notifyEventUpdate() {
         | 
| 397 | 
            -
                    this.connectionCallbacks.event.forEach(callback => | 
| 408 | 
            +
                    this.connectionCallbacks.event.forEach(callback =>
         | 
| 398 409 | 
             
                        callback(this.events, this.sessions)
         | 
| 399 410 | 
             
                    );
         | 
| 400 | 
            -
             | 
| 411 | 
            +
             | 
| 401 412 | 
             
                    // Also dispatch custom event
         | 
| 402 413 | 
             
                    document.dispatchEvent(new CustomEvent('socketEventUpdate', {
         | 
| 403 414 | 
             
                        detail: { events: this.events, sessions: this.sessions }
         | 
| @@ -422,39 +433,104 @@ class SocketClient { | |
| 422 433 | 
             
                 * @returns {Object} Transformed event
         | 
| 423 434 | 
             
                 */
         | 
| 424 435 | 
             
                transformEvent(eventData) {
         | 
| 425 | 
            -
                    // Handle  | 
| 426 | 
            -
                    // { type: 'hook.pre_tool', timestamp: '...', data: { | 
| 427 | 
            -
                    
         | 
| 428 | 
            -
                     | 
| 429 | 
            -
             | 
| 436 | 
            +
                    // Handle multiple event structures:
         | 
| 437 | 
            +
                    // 1. Hook events: { type: 'hook.pre_tool', timestamp: '...', data: {...} }
         | 
| 438 | 
            +
                    // 2. Legacy events: { event: 'TestStart', timestamp: '...', ... }
         | 
| 439 | 
            +
                    // 3. Standard events: { type: 'session', subtype: 'started', ... }
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                    if (!eventData) {
         | 
| 442 | 
            +
                        return eventData; // Return as-is if null/undefined
         | 
| 430 443 | 
             
                    }
         | 
| 431 444 |  | 
| 432 | 
            -
                    const type = eventData.type;
         | 
| 433 445 | 
             
                    let transformedEvent = { ...eventData };
         | 
| 434 446 |  | 
| 435 | 
            -
                    //  | 
| 436 | 
            -
                    if (type. | 
| 437 | 
            -
                         | 
| 438 | 
            -
                         | 
| 439 | 
            -
                         | 
| 447 | 
            +
                    // Handle legacy format with 'event' field but no 'type'
         | 
| 448 | 
            +
                    if (!eventData.type && eventData.event) {
         | 
| 449 | 
            +
                        // Map common event names to proper type/subtype
         | 
| 450 | 
            +
                        const eventName = eventData.event;
         | 
| 451 | 
            +
                        
         | 
| 452 | 
            +
                        // Check for known event patterns
         | 
| 453 | 
            +
                        if (eventName === 'TestStart' || eventName === 'TestEnd') {
         | 
| 454 | 
            +
                            transformedEvent.type = 'test';
         | 
| 455 | 
            +
                            transformedEvent.subtype = eventName.toLowerCase().replace('test', '');
         | 
| 456 | 
            +
                        } else if (eventName === 'SubagentStart' || eventName === 'SubagentStop') {
         | 
| 457 | 
            +
                            transformedEvent.type = 'subagent';
         | 
| 458 | 
            +
                            transformedEvent.subtype = eventName.toLowerCase().replace('subagent', '');
         | 
| 459 | 
            +
                        } else if (eventName === 'ToolCall') {
         | 
| 460 | 
            +
                            transformedEvent.type = 'tool';
         | 
| 461 | 
            +
                            transformedEvent.subtype = 'call';
         | 
| 462 | 
            +
                        } else if (eventName === 'UserPrompt') {
         | 
| 463 | 
            +
                            transformedEvent.type = 'hook';
         | 
| 464 | 
            +
                            transformedEvent.subtype = 'user_prompt';
         | 
| 465 | 
            +
                        } else {
         | 
| 466 | 
            +
                            // Generic fallback for unknown event names
         | 
| 467 | 
            +
                            transformedEvent.type = 'system';
         | 
| 468 | 
            +
                            transformedEvent.subtype = eventName.toLowerCase();
         | 
| 469 | 
            +
                        }
         | 
| 470 | 
            +
                        
         | 
| 471 | 
            +
                        // Remove the 'event' field to avoid confusion
         | 
| 472 | 
            +
                        delete transformedEvent.event;
         | 
| 473 | 
            +
                    }
         | 
| 474 | 
            +
                    // Handle standard format with 'type' field
         | 
| 475 | 
            +
                    else if (eventData.type) {
         | 
| 476 | 
            +
                        const type = eventData.type;
         | 
| 477 | 
            +
                        
         | 
| 478 | 
            +
                        // Transform 'hook.subtype' format to separate type and subtype
         | 
| 479 | 
            +
                        if (type.startsWith('hook.')) {
         | 
| 480 | 
            +
                            const subtype = type.substring(5); // Remove 'hook.' prefix
         | 
| 481 | 
            +
                            transformedEvent.type = 'hook';
         | 
| 482 | 
            +
                            transformedEvent.subtype = subtype;
         | 
| 483 | 
            +
                        }
         | 
| 484 | 
            +
                        // Transform other dotted types like 'session.started' -> type: 'session', subtype: 'started'
         | 
| 485 | 
            +
                        else if (type.includes('.')) {
         | 
| 486 | 
            +
                            const [mainType, ...subtypeParts] = type.split('.');
         | 
| 487 | 
            +
                            transformedEvent.type = mainType;
         | 
| 488 | 
            +
                            transformedEvent.subtype = subtypeParts.join('.');
         | 
| 489 | 
            +
                        }
         | 
| 440 490 | 
             
                    }
         | 
| 441 | 
            -
                    //  | 
| 442 | 
            -
                    else  | 
| 443 | 
            -
                         | 
| 444 | 
            -
                        transformedEvent. | 
| 445 | 
            -
             | 
| 491 | 
            +
                    // If no type and no event field, mark as unknown
         | 
| 492 | 
            +
                    else {
         | 
| 493 | 
            +
                        transformedEvent.type = 'unknown';
         | 
| 494 | 
            +
                        transformedEvent.subtype = '';
         | 
| 495 | 
            +
                    }
         | 
| 496 | 
            +
             | 
| 497 | 
            +
                    // Store original event name for display purposes (before any transformation)
         | 
| 498 | 
            +
                    if (!eventData.type && eventData.event) {
         | 
| 499 | 
            +
                        transformedEvent.originalEventName = eventData.event;
         | 
| 500 | 
            +
                    } else if (eventData.type) {
         | 
| 501 | 
            +
                        transformedEvent.originalEventName = eventData.type;
         | 
| 446 502 | 
             
                    }
         | 
| 447 503 |  | 
| 448 504 | 
             
                    // Extract and flatten data fields to top level for dashboard compatibility
         | 
| 449 505 | 
             
                    // The dashboard expects fields like tool_name, agent_type, etc. at the top level
         | 
| 450 506 | 
             
                    if (eventData.data && typeof eventData.data === 'object') {
         | 
| 451 | 
            -
                        //  | 
| 507 | 
            +
                        // Protected fields that should never be overwritten by data fields
         | 
| 508 | 
            +
                        const protectedFields = ['type', 'subtype', 'timestamp', 'id', 'event', 'event_type', 'originalEventName'];
         | 
| 509 | 
            +
                        
         | 
| 510 | 
            +
                        // Copy all data fields to the top level, except protected ones
         | 
| 452 511 | 
             
                        Object.keys(eventData.data).forEach(key => {
         | 
| 453 | 
            -
                            // Only copy if  | 
| 454 | 
            -
                            if (!(key | 
| 512 | 
            +
                            // Only copy if not a protected field
         | 
| 513 | 
            +
                            if (!protectedFields.includes(key)) {
         | 
| 455 514 | 
             
                                transformedEvent[key] = eventData.data[key];
         | 
| 515 | 
            +
                            } else {
         | 
| 516 | 
            +
                                // Log warning if data field would overwrite a protected field
         | 
| 517 | 
            +
                                console.warn(`Protected field '${key}' in data object was not copied to top level to preserve event structure`);
         | 
| 456 518 | 
             
                            }
         | 
| 457 519 | 
             
                        });
         | 
| 520 | 
            +
                        
         | 
| 521 | 
            +
                        // Keep the original data object for backward compatibility
         | 
| 522 | 
            +
                        transformedEvent.data = eventData.data;
         | 
| 523 | 
            +
                    }
         | 
| 524 | 
            +
             | 
| 525 | 
            +
                    // Debug logging for tool events
         | 
| 526 | 
            +
                    if (transformedEvent.type === 'hook' && (transformedEvent.subtype === 'pre_tool' || transformedEvent.subtype === 'post_tool')) {
         | 
| 527 | 
            +
                        console.log('Transformed tool event:', {
         | 
| 528 | 
            +
                            type: transformedEvent.type,
         | 
| 529 | 
            +
                            subtype: transformedEvent.subtype,
         | 
| 530 | 
            +
                            tool_name: transformedEvent.tool_name,
         | 
| 531 | 
            +
                            has_data: !!transformedEvent.data,
         | 
| 532 | 
            +
                            keys: Object.keys(transformedEvent).filter(k => k !== 'data')
         | 
| 533 | 
            +
                        });
         | 
| 458 534 | 
             
                    }
         | 
| 459 535 |  | 
| 460 536 | 
             
                    return transformedEvent;
         | 
| @@ -481,7 +557,7 @@ class SocketClient { | |
| 481 557 | 
             
                    setInterval(() => {
         | 
| 482 558 | 
             
                        this.checkAndUpdateStatus();
         | 
| 483 559 | 
             
                    }, 2000);
         | 
| 484 | 
            -
             | 
| 560 | 
            +
             | 
| 485 561 | 
             
                    // Initial check after DOM is ready
         | 
| 486 562 | 
             
                    if (document.readyState === 'loading') {
         | 
| 487 563 | 
             
                        document.addEventListener('DOMContentLoaded', () => {
         | 
| @@ -498,7 +574,7 @@ class SocketClient { | |
| 498 574 | 
             
                checkAndUpdateStatus() {
         | 
| 499 575 | 
             
                    let actualStatus = 'Disconnected';
         | 
| 500 576 | 
             
                    let actualType = 'disconnected';
         | 
| 501 | 
            -
             | 
| 577 | 
            +
             | 
| 502 578 | 
             
                    if (this.socket) {
         | 
| 503 579 | 
             
                        if (this.socket.connected) {
         | 
| 504 580 | 
             
                            actualStatus = 'Connected';
         | 
| @@ -516,14 +592,14 @@ class SocketClient { | |
| 516 592 | 
             
                            this.isConnecting = false;
         | 
| 517 593 | 
             
                        }
         | 
| 518 594 | 
             
                    }
         | 
| 519 | 
            -
             | 
| 595 | 
            +
             | 
| 520 596 | 
             
                    // Check if UI needs updating
         | 
| 521 597 | 
             
                    const statusElement = document.getElementById('connection-status');
         | 
| 522 598 | 
             
                    if (statusElement) {
         | 
| 523 599 | 
             
                        const currentText = statusElement.textContent.replace('●', '').trim();
         | 
| 524 600 | 
             
                        const currentClass = statusElement.className;
         | 
| 525 601 | 
             
                        const expectedClass = `status-badge status-${actualType}`;
         | 
| 526 | 
            -
             | 
| 602 | 
            +
             | 
| 527 603 | 
             
                        // Update if status text or class doesn't match
         | 
| 528 604 | 
             
                        if (currentText !== actualStatus || currentClass !== expectedClass) {
         | 
| 529 605 | 
             
                            console.log(`SocketClient: Fallback update - was '${currentText}' (${currentClass}), now '${actualStatus}' (${expectedClass})`);
         | 
| @@ -533,5 +609,9 @@ class SocketClient { | |
| 533 609 | 
             
                }
         | 
| 534 610 | 
             
            }
         | 
| 535 611 |  | 
| 536 | 
            -
            //  | 
| 537 | 
            -
             | 
| 612 | 
            +
            // ES6 Module export
         | 
| 613 | 
            +
            export { SocketClient };
         | 
| 614 | 
            +
            export default SocketClient;
         | 
| 615 | 
            +
             | 
| 616 | 
            +
            // Backward compatibility - keep window export for non-module usage
         | 
| 617 | 
            +
            window.SocketClient = SocketClient;
         |