claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +2 -2
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +140 -905
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +330 -86
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +363 -220
- claude_mpm/cli/parser.py +24 -1156
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +124 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/built/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/built/dashboard.js +2 -0
- claude_mpm/dashboard/static/built/socket-client.js +2 -0
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +133 -53
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +233 -199
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +30 -13
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +575 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +166 -64
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +185 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +19 -533
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
- claude_mpm-4.0.4.dist-info/RECORD +417 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
| @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            /**
         | 
| 2 2 | 
             
             * File and Tool Tracker Module
         | 
| 3 | 
            -
             * | 
| 3 | 
            +
             *
         | 
| 4 4 | 
             
             * Tracks file operations and tool calls by pairing pre/post events and maintaining
         | 
| 5 5 | 
             
             * organized collections for the files and tools tabs. Provides analysis of
         | 
| 6 6 | 
             
             * tool execution patterns and file operation history.
         | 
| 7 | 
            -
             * | 
| 7 | 
            +
             *
         | 
| 8 8 | 
             
             * WHY: Extracted from main dashboard to isolate complex event pairing logic
         | 
| 9 9 | 
             
             * that groups related events into meaningful operations. This provides better
         | 
| 10 10 | 
             
             * maintainability for the intricate logic of matching tool events with their results.
         | 
| 11 | 
            -
             * | 
| 11 | 
            +
             *
         | 
| 12 12 | 
             
             * DESIGN DECISION: Uses intelligent correlation strategy for tool calls that:
         | 
| 13 13 | 
             
             * - Separates pre_tool and post_tool events first
         | 
| 14 14 | 
             
             * - Correlates based on temporal proximity, parameter similarity, and context
         | 
| @@ -20,13 +20,13 @@ class FileToolTracker { | |
| 20 20 | 
             
                constructor(agentInference, workingDirectoryManager) {
         | 
| 21 21 | 
             
                    this.agentInference = agentInference;
         | 
| 22 22 | 
             
                    this.workingDirectoryManager = workingDirectoryManager;
         | 
| 23 | 
            -
             | 
| 23 | 
            +
             | 
| 24 24 | 
             
                    // File tracking for files tab
         | 
| 25 25 | 
             
                    this.fileOperations = new Map(); // Map of file paths to operations
         | 
| 26 | 
            -
             | 
| 26 | 
            +
             | 
| 27 27 | 
             
                    // Tool call tracking for tools tab
         | 
| 28 28 | 
             
                    this.toolCalls = new Map(); // Map of tool call keys to paired pre/post events
         | 
| 29 | 
            -
             | 
| 29 | 
            +
             | 
| 30 30 | 
             
                    console.log('File-tool tracker initialized');
         | 
| 31 31 | 
             
                }
         | 
| 32 32 |  | 
| @@ -43,12 +43,12 @@ class FileToolTracker { | |
| 43 43 | 
             
                    // Group events by session and timestamp to match pre/post pairs
         | 
| 44 44 | 
             
                    const eventPairs = new Map(); // Key: session_id + timestamp + tool_name
         | 
| 45 45 | 
             
                    let fileOperationCount = 0;
         | 
| 46 | 
            -
             | 
| 46 | 
            +
             | 
| 47 47 | 
             
                    // First pass: collect all tool events and group them
         | 
| 48 48 | 
             
                    events.forEach((event, index) => {
         | 
| 49 49 | 
             
                        const isFileOp = this.isFileOperation(event);
         | 
| 50 50 | 
             
                        if (isFileOp) fileOperationCount++;
         | 
| 51 | 
            -
             | 
| 51 | 
            +
             | 
| 52 52 | 
             
                        if (index < 5) { // Debug first 5 events with more detail
         | 
| 53 53 | 
             
                            console.log(`Event ${index}:`, {
         | 
| 54 54 | 
             
                                type: event.type,
         | 
| @@ -58,12 +58,12 @@ class FileToolTracker { | |
| 58 58 | 
             
                                isFileOp: isFileOp
         | 
| 59 59 | 
             
                            });
         | 
| 60 60 | 
             
                        }
         | 
| 61 | 
            -
             | 
| 61 | 
            +
             | 
| 62 62 | 
             
                        if (isFileOp) {
         | 
| 63 | 
            -
                            const toolName = event.tool_name;
         | 
| 64 | 
            -
                            const sessionId = event.session_id || 'unknown';
         | 
| 63 | 
            +
                            const toolName = event.tool_name || (event.data && event.data.tool_name);
         | 
| 64 | 
            +
                            const sessionId = event.session_id || (event.data && event.data.session_id) || 'unknown';
         | 
| 65 65 | 
             
                            const eventKey = `${sessionId}_${toolName}_${Math.floor(new Date(event.timestamp).getTime() / 1000)}`; // Group by second
         | 
| 66 | 
            -
             | 
| 66 | 
            +
             | 
| 67 67 | 
             
                            if (!eventPairs.has(eventKey)) {
         | 
| 68 68 | 
             
                                eventPairs.set(eventKey, {
         | 
| 69 69 | 
             
                                    pre_event: null,
         | 
| @@ -72,11 +72,11 @@ class FileToolTracker { | |
| 72 72 | 
             
                                    session_id: sessionId
         | 
| 73 73 | 
             
                                });
         | 
| 74 74 | 
             
                            }
         | 
| 75 | 
            -
             | 
| 75 | 
            +
             | 
| 76 76 | 
             
                            const pair = eventPairs.get(eventKey);
         | 
| 77 | 
            -
                            if (event.subtype === 'pre_tool' || event.type === 'hook' && !event.subtype.includes('post')) {
         | 
| 77 | 
            +
                            if (event.subtype === 'pre_tool' || (event.type === 'hook' && event.subtype && !event.subtype.includes('post'))) {
         | 
| 78 78 | 
             
                                pair.pre_event = event;
         | 
| 79 | 
            -
                            } else if (event.subtype === 'post_tool' || event.subtype.includes('post')) {
         | 
| 79 | 
            +
                            } else if (event.subtype === 'post_tool' || (event.subtype && event.subtype.includes('post'))) {
         | 
| 80 80 | 
             
                                pair.post_event = event;
         | 
| 81 81 | 
             
                            } else {
         | 
| 82 82 | 
             
                                // For events without clear pre/post distinction, treat as both
         | 
| @@ -85,16 +85,16 @@ class FileToolTracker { | |
| 85 85 | 
             
                            }
         | 
| 86 86 | 
             
                        }
         | 
| 87 87 | 
             
                    });
         | 
| 88 | 
            -
             | 
| 88 | 
            +
             | 
| 89 89 | 
             
                    console.log('updateFileOperations - found', fileOperationCount, 'file operations in', eventPairs.size, 'event pairs');
         | 
| 90 | 
            -
             | 
| 90 | 
            +
             | 
| 91 91 | 
             
                    // Second pass: extract file paths and operations from paired events
         | 
| 92 92 | 
             
                    eventPairs.forEach((pair, key) => {
         | 
| 93 93 | 
             
                        const filePath = this.extractFilePathFromPair(pair);
         | 
| 94 | 
            -
             | 
| 94 | 
            +
             | 
| 95 95 | 
             
                        if (filePath) {
         | 
| 96 96 | 
             
                            console.log('File operation detected for:', filePath, 'from pair:', key);
         | 
| 97 | 
            -
             | 
| 97 | 
            +
             | 
| 98 98 | 
             
                            if (!this.fileOperations.has(filePath)) {
         | 
| 99 99 | 
             
                                this.fileOperations.set(filePath, {
         | 
| 100 100 | 
             
                                    path: filePath,
         | 
| @@ -106,10 +106,10 @@ class FileToolTracker { | |
| 106 106 | 
             
                            const fileData = this.fileOperations.get(filePath);
         | 
| 107 107 | 
             
                            const operation = this.getFileOperationFromPair(pair);
         | 
| 108 108 | 
             
                            const timestamp = pair.post_event?.timestamp || pair.pre_event?.timestamp;
         | 
| 109 | 
            -
             | 
| 109 | 
            +
             | 
| 110 110 | 
             
                            const agentInfo = this.extractAgentFromPair(pair);
         | 
| 111 111 | 
             
                            const workingDirectory = this.workingDirectoryManager.extractWorkingDirectoryFromPair(pair);
         | 
| 112 | 
            -
             | 
| 112 | 
            +
             | 
| 113 113 | 
             
                            fileData.operations.push({
         | 
| 114 114 | 
             
                                operation: operation,
         | 
| 115 115 | 
             
                                timestamp: timestamp,
         | 
| @@ -124,7 +124,7 @@ class FileToolTracker { | |
| 124 124 | 
             
                            console.log('No file path found for pair:', key, pair);
         | 
| 125 125 | 
             
                        }
         | 
| 126 126 | 
             
                    });
         | 
| 127 | 
            -
             | 
| 127 | 
            +
             | 
| 128 128 | 
             
                    console.log('updateFileOperations - final result:', this.fileOperations.size, 'file operations');
         | 
| 129 129 | 
             
                    if (this.fileOperations.size > 0) {
         | 
| 130 130 | 
             
                        console.log('File operations map:', Array.from(this.fileOperations.entries()));
         | 
| @@ -145,12 +145,12 @@ class FileToolTracker { | |
| 145 145 | 
             
                    const preToolEvents = [];
         | 
| 146 146 | 
             
                    const postToolEvents = [];
         | 
| 147 147 | 
             
                    let toolOperationCount = 0;
         | 
| 148 | 
            -
             | 
| 148 | 
            +
             | 
| 149 149 | 
             
                    // First pass: separate pre_tool and post_tool events
         | 
| 150 150 | 
             
                    events.forEach((event, index) => {
         | 
| 151 151 | 
             
                        const isToolOp = this.isToolOperation(event);
         | 
| 152 152 | 
             
                        if (isToolOp) toolOperationCount++;
         | 
| 153 | 
            -
             | 
| 153 | 
            +
             | 
| 154 154 | 
             
                        if (index < 5) { // Debug first 5 events with more detail
         | 
| 155 155 | 
             
                            console.log(`Tool Event ${index}:`, {
         | 
| 156 156 | 
             
                                type: event.type,
         | 
| @@ -160,11 +160,11 @@ class FileToolTracker { | |
| 160 160 | 
             
                                isToolOp: isToolOp
         | 
| 161 161 | 
             
                            });
         | 
| 162 162 | 
             
                        }
         | 
| 163 | 
            -
             | 
| 163 | 
            +
             | 
| 164 164 | 
             
                        if (isToolOp) {
         | 
| 165 | 
            -
                            if (event.subtype === 'pre_tool' || (event.type === 'hook' && !event.subtype.includes('post'))) {
         | 
| 165 | 
            +
                            if (event.subtype === 'pre_tool' || (event.type === 'hook' && event.subtype && !event.subtype.includes('post'))) {
         | 
| 166 166 | 
             
                                preToolEvents.push(event);
         | 
| 167 | 
            -
                            } else if (event.subtype === 'post_tool' || event.subtype.includes('post')) {
         | 
| 167 | 
            +
                            } else if (event.subtype === 'post_tool' || (event.subtype && event.subtype.includes('post'))) {
         | 
| 168 168 | 
             
                                postToolEvents.push(event);
         | 
| 169 169 | 
             
                            } else {
         | 
| 170 170 | 
             
                                // For events without clear pre/post distinction, treat as standalone
         | 
| @@ -173,18 +173,18 @@ class FileToolTracker { | |
| 173 173 | 
             
                            }
         | 
| 174 174 | 
             
                        }
         | 
| 175 175 | 
             
                    });
         | 
| 176 | 
            -
             | 
| 176 | 
            +
             | 
| 177 177 | 
             
                    console.log('updateToolCalls - found', toolOperationCount, 'tool operations:', preToolEvents.length, 'pre_tool,', postToolEvents.length, 'post_tool');
         | 
| 178 | 
            -
             | 
| 178 | 
            +
             | 
| 179 179 | 
             
                    // Second pass: correlate pre_tool events with post_tool events
         | 
| 180 180 | 
             
                    const toolCallPairs = new Map();
         | 
| 181 181 | 
             
                    const usedPostEvents = new Set();
         | 
| 182 | 
            -
             | 
| 182 | 
            +
             | 
| 183 183 | 
             
                    preToolEvents.forEach((preEvent, preIndex) => {
         | 
| 184 | 
            -
                        const toolName = preEvent.tool_name;
         | 
| 185 | 
            -
                        const sessionId = preEvent.session_id || 'unknown';
         | 
| 184 | 
            +
                        const toolName = preEvent.tool_name || (preEvent.data && preEvent.data.tool_name);
         | 
| 185 | 
            +
                        const sessionId = preEvent.session_id || (preEvent.data && preEvent.data.session_id) || 'unknown';
         | 
| 186 186 | 
             
                        const preTimestamp = new Date(preEvent.timestamp).getTime();
         | 
| 187 | 
            -
             | 
| 187 | 
            +
             | 
| 188 188 | 
             
                        // Create a base pair for this pre_tool event
         | 
| 189 189 | 
             
                        const pairKey = `${sessionId}_${toolName}_${preIndex}_${preTimestamp}`;
         | 
| 190 190 | 
             
                        const pair = {
         | 
| @@ -201,53 +201,55 @@ class FileToolTracker { | |
| 201 201 | 
             
                            agent_type: null,
         | 
| 202 202 | 
             
                            agent_confidence: null
         | 
| 203 203 | 
             
                        };
         | 
| 204 | 
            -
             | 
| 204 | 
            +
             | 
| 205 205 | 
             
                        // Get agent info from pre_event
         | 
| 206 206 | 
             
                        const agentInfo = this.extractAgentFromEvent(preEvent);
         | 
| 207 207 | 
             
                        pair.agent_type = agentInfo.name;
         | 
| 208 208 | 
             
                        pair.agent_confidence = agentInfo.confidence;
         | 
| 209 | 
            -
             | 
| 209 | 
            +
             | 
| 210 210 | 
             
                        // Try to find matching post_tool event
         | 
| 211 211 | 
             
                        let bestMatchIndex = -1;
         | 
| 212 212 | 
             
                        let bestMatchScore = -1;
         | 
| 213 213 | 
             
                        const maxTimeDiffMs = 300000; // 5 minutes max time difference
         | 
| 214 | 
            -
             | 
| 214 | 
            +
             | 
| 215 215 | 
             
                        postToolEvents.forEach((postEvent, postIndex) => {
         | 
| 216 216 | 
             
                            // Skip already used post events
         | 
| 217 217 | 
             
                            if (usedPostEvents.has(postIndex)) return;
         | 
| 218 | 
            -
             | 
| 218 | 
            +
             | 
| 219 219 | 
             
                            // Must match tool name and session
         | 
| 220 | 
            -
                             | 
| 221 | 
            -
                            
         | 
| 220 | 
            +
                            const postToolName = postEvent.tool_name || (postEvent.data && postEvent.data.tool_name);
         | 
| 221 | 
            +
                            const postSessionId = postEvent.session_id || (postEvent.data && postEvent.data.session_id) || 'unknown';
         | 
| 222 | 
            +
                            if (postToolName !== toolName || postSessionId !== sessionId) return;
         | 
| 223 | 
            +
             | 
| 222 224 | 
             
                            const postTimestamp = new Date(postEvent.timestamp).getTime();
         | 
| 223 225 | 
             
                            const timeDiff = Math.abs(postTimestamp - preTimestamp);
         | 
| 224 | 
            -
             | 
| 226 | 
            +
             | 
| 225 227 | 
             
                            // Post event should generally come after pre event (or very close)
         | 
| 226 228 | 
             
                            const isTemporallyValid = postTimestamp >= preTimestamp - 1000; // Allow 1s clock skew
         | 
| 227 | 
            -
             | 
| 229 | 
            +
             | 
| 228 230 | 
             
                            // Calculate correlation score (higher is better)
         | 
| 229 231 | 
             
                            let score = 0;
         | 
| 230 232 | 
             
                            if (isTemporallyValid && timeDiff <= maxTimeDiffMs) {
         | 
| 231 233 | 
             
                                score = 1000 - (timeDiff / 1000); // Prefer closer timestamps
         | 
| 232 | 
            -
             | 
| 234 | 
            +
             | 
| 233 235 | 
             
                                // Boost score for parameter similarity (if available)
         | 
| 234 236 | 
             
                                if (this.compareToolParameters(preEvent, postEvent)) {
         | 
| 235 237 | 
             
                                    score += 500;
         | 
| 236 238 | 
             
                                }
         | 
| 237 | 
            -
             | 
| 239 | 
            +
             | 
| 238 240 | 
             
                                // Boost score for same working directory
         | 
| 239 | 
            -
                                if (preEvent.working_directory && postEvent.working_directory && | 
| 241 | 
            +
                                if (preEvent.working_directory && postEvent.working_directory &&
         | 
| 240 242 | 
             
                                    preEvent.working_directory === postEvent.working_directory) {
         | 
| 241 243 | 
             
                                    score += 100;
         | 
| 242 244 | 
             
                                }
         | 
| 243 245 | 
             
                            }
         | 
| 244 | 
            -
             | 
| 246 | 
            +
             | 
| 245 247 | 
             
                            if (score > bestMatchScore) {
         | 
| 246 248 | 
             
                                bestMatchScore = score;
         | 
| 247 249 | 
             
                                bestMatchIndex = postIndex;
         | 
| 248 250 | 
             
                            }
         | 
| 249 251 | 
             
                        });
         | 
| 250 | 
            -
             | 
| 252 | 
            +
             | 
| 251 253 | 
             
                        // If we found a good match, pair them
         | 
| 252 254 | 
             
                        if (bestMatchIndex >= 0 && bestMatchScore > 0) {
         | 
| 253 255 | 
             
                            const postEvent = postToolEvents[bestMatchIndex];
         | 
| @@ -256,26 +258,26 @@ class FileToolTracker { | |
| 256 258 | 
             
                            pair.success = postEvent.success;
         | 
| 257 259 | 
             
                            pair.exit_code = postEvent.exit_code;
         | 
| 258 260 | 
             
                            pair.result_summary = postEvent.result_summary;
         | 
| 259 | 
            -
             | 
| 261 | 
            +
             | 
| 260 262 | 
             
                            usedPostEvents.add(bestMatchIndex);
         | 
| 261 263 | 
             
                            console.log(`Paired pre_tool ${toolName} at ${preEvent.timestamp} with post_tool at ${postEvent.timestamp} (score: ${bestMatchScore})`);
         | 
| 262 264 | 
             
                        } else {
         | 
| 263 265 | 
             
                            console.log(`No matching post_tool found for ${toolName} at ${preEvent.timestamp} (still running or orphaned)`);
         | 
| 264 266 | 
             
                        }
         | 
| 265 | 
            -
             | 
| 267 | 
            +
             | 
| 266 268 | 
             
                        toolCallPairs.set(pairKey, pair);
         | 
| 267 269 | 
             
                    });
         | 
| 268 | 
            -
             | 
| 270 | 
            +
             | 
| 269 271 | 
             
                    // Third pass: handle any orphaned post_tool events (shouldn't happen but be safe)
         | 
| 270 272 | 
             
                    postToolEvents.forEach((postEvent, postIndex) => {
         | 
| 271 273 | 
             
                        if (usedPostEvents.has(postIndex)) return;
         | 
| 272 | 
            -
             | 
| 273 | 
            -
                         | 
| 274 | 
            -
                        
         | 
| 275 | 
            -
             | 
| 276 | 
            -
                        const sessionId = postEvent.session_id || 'unknown';
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                        const toolName = postEvent.tool_name || (postEvent.data && postEvent.data.tool_name);
         | 
| 276 | 
            +
                        console.log('Orphaned post_tool event found:', toolName, 'at', postEvent.timestamp);
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                        const sessionId = postEvent.session_id || (postEvent.data && postEvent.data.session_id) || 'unknown';
         | 
| 277 279 | 
             
                        const postTimestamp = new Date(postEvent.timestamp).getTime();
         | 
| 278 | 
            -
             | 
| 280 | 
            +
             | 
| 279 281 | 
             
                        const pairKey = `orphaned_${sessionId}_${toolName}_${postIndex}_${postTimestamp}`;
         | 
| 280 282 | 
             
                        const pair = {
         | 
| 281 283 | 
             
                            pre_event: null,
         | 
| @@ -291,17 +293,17 @@ class FileToolTracker { | |
| 291 293 | 
             
                            agent_type: null,
         | 
| 292 294 | 
             
                            agent_confidence: null
         | 
| 293 295 | 
             
                        };
         | 
| 294 | 
            -
             | 
| 296 | 
            +
             | 
| 295 297 | 
             
                        const agentInfo = this.extractAgentFromEvent(postEvent);
         | 
| 296 298 | 
             
                        pair.agent_type = agentInfo.name;
         | 
| 297 299 | 
             
                        pair.agent_confidence = agentInfo.confidence;
         | 
| 298 | 
            -
             | 
| 300 | 
            +
             | 
| 299 301 | 
             
                        toolCallPairs.set(pairKey, pair);
         | 
| 300 302 | 
             
                    });
         | 
| 301 | 
            -
             | 
| 303 | 
            +
             | 
| 302 304 | 
             
                    // Store the correlated tool calls
         | 
| 303 305 | 
             
                    this.toolCalls = toolCallPairs;
         | 
| 304 | 
            -
             | 
| 306 | 
            +
             | 
| 305 307 | 
             
                    console.log('updateToolCalls - final result:', this.toolCalls.size, 'tool calls');
         | 
| 306 308 | 
             
                    if (this.toolCalls.size > 0) {
         | 
| 307 309 | 
             
                        console.log('Tool calls map keys:', Array.from(this.toolCalls.keys()));
         | 
| @@ -315,10 +317,13 @@ class FileToolTracker { | |
| 315 317 | 
             
                 */
         | 
| 316 318 | 
             
                isToolOperation(event) {
         | 
| 317 319 | 
             
                    // Tool operations have tool_name and are hook events with pre_tool or post_tool subtype
         | 
| 318 | 
            -
                     | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 320 | 
            +
                    // Check both top-level and data.tool_name for compatibility
         | 
| 321 | 
            +
                    const hasToolName = event.tool_name || (event.data && event.data.tool_name);
         | 
| 322 | 
            +
                    const isHookEvent = event.type === 'hook';
         | 
| 323 | 
            +
                    const isToolSubtype = event.subtype === 'pre_tool' || event.subtype === 'post_tool' ||
         | 
| 324 | 
            +
                                          (event.subtype && typeof event.subtype === 'string' && event.subtype.includes('tool'));
         | 
| 325 | 
            +
                    
         | 
| 326 | 
            +
                    return hasToolName && isHookEvent && isToolSubtype;
         | 
| 322 327 | 
             
                }
         | 
| 323 328 |  | 
| 324 329 | 
             
                /**
         | 
| @@ -328,19 +333,25 @@ class FileToolTracker { | |
| 328 333 | 
             
                 */
         | 
| 329 334 | 
             
                isFileOperation(event) {
         | 
| 330 335 | 
             
                    // File operations are tool events with tools that operate on files
         | 
| 336 | 
            +
                    // Check both top-level and data for tool_name
         | 
| 337 | 
            +
                    let toolName = event.tool_name || (event.data && event.data.tool_name) || '';
         | 
| 338 | 
            +
                    toolName = toolName.toLowerCase();
         | 
| 339 | 
            +
                    
         | 
| 331 340 | 
             
                    // Check case-insensitively since tool names can come in different cases
         | 
| 332 341 | 
             
                    const fileTools = ['read', 'write', 'edit', 'grep', 'multiedit', 'glob', 'ls', 'bash', 'notebookedit'];
         | 
| 333 | 
            -
                    const toolName = event.tool_name ? event.tool_name.toLowerCase() : '';
         | 
| 334 342 |  | 
| 343 | 
            +
                    // Get tool parameters from either location
         | 
| 344 | 
            +
                    const toolParams = event.tool_parameters || (event.data && event.data.tool_parameters);
         | 
| 345 | 
            +
             | 
| 335 346 | 
             
                    // Also check if Bash commands involve file operations
         | 
| 336 | 
            -
                    if (toolName === 'bash' &&  | 
| 337 | 
            -
                        const command =  | 
| 347 | 
            +
                    if (toolName === 'bash' && toolParams) {
         | 
| 348 | 
            +
                        const command = toolParams.command || '';
         | 
| 338 349 | 
             
                        // Check for common file operations in bash commands
         | 
| 339 350 | 
             
                        if (command.match(/\b(cat|less|more|head|tail|touch|mv|cp|rm|mkdir|ls|find)\b/)) {
         | 
| 340 351 | 
             
                            return true;
         | 
| 341 352 | 
             
                        }
         | 
| 342 353 | 
             
                    }
         | 
| 343 | 
            -
             | 
| 354 | 
            +
             | 
| 344 355 | 
             
                    return toolName && fileTools.includes(toolName);
         | 
| 345 356 | 
             
                }
         | 
| 346 357 |  | 
| @@ -359,12 +370,12 @@ class FileToolTracker { | |
| 359 370 | 
             
                    if (event.data?.tool_parameters?.notebook_path) return event.data.tool_parameters.notebook_path;
         | 
| 360 371 | 
             
                    if (event.file_path) return event.file_path;
         | 
| 361 372 | 
             
                    if (event.path) return event.path;
         | 
| 362 | 
            -
             | 
| 373 | 
            +
             | 
| 363 374 | 
             
                    // For Glob tool, use the pattern as a pseudo-path
         | 
| 364 375 | 
             
                    if (event.tool_name?.toLowerCase() === 'glob' && event.tool_parameters?.pattern) {
         | 
| 365 376 | 
             
                        return `[glob] ${event.tool_parameters.pattern}`;
         | 
| 366 377 | 
             
                    }
         | 
| 367 | 
            -
             | 
| 378 | 
            +
             | 
| 368 379 | 
             
                    // For Bash commands, try to extract file paths from the command
         | 
| 369 380 | 
             
                    if (event.tool_name?.toLowerCase() === 'bash' && event.tool_parameters?.command) {
         | 
| 370 381 | 
             
                        const command = event.tool_parameters.command;
         | 
| @@ -374,7 +385,7 @@ class FileToolTracker { | |
| 374 385 | 
             
                            return fileMatch[1];
         | 
| 375 386 | 
             
                        }
         | 
| 376 387 | 
             
                    }
         | 
| 377 | 
            -
             | 
| 388 | 
            +
             | 
| 378 389 | 
             
                    return null;
         | 
| 379 390 | 
             
                }
         | 
| 380 391 |  | 
| @@ -386,15 +397,15 @@ class FileToolTracker { | |
| 386 397 | 
             
                extractFilePathFromPair(pair) {
         | 
| 387 398 | 
             
                    // Try pre_event first, then post_event
         | 
| 388 399 | 
             
                    let filePath = null;
         | 
| 389 | 
            -
             | 
| 400 | 
            +
             | 
| 390 401 | 
             
                    if (pair.pre_event) {
         | 
| 391 402 | 
             
                        filePath = this.extractFilePath(pair.pre_event);
         | 
| 392 403 | 
             
                    }
         | 
| 393 | 
            -
             | 
| 404 | 
            +
             | 
| 394 405 | 
             
                    if (!filePath && pair.post_event) {
         | 
| 395 406 | 
             
                        filePath = this.extractFilePath(pair.post_event);
         | 
| 396 407 | 
             
                    }
         | 
| 397 | 
            -
             | 
| 408 | 
            +
             | 
| 398 409 | 
             
                    return filePath;
         | 
| 399 410 | 
             
                }
         | 
| 400 411 |  | 
| @@ -405,7 +416,7 @@ class FileToolTracker { | |
| 405 416 | 
             
                 */
         | 
| 406 417 | 
             
                getFileOperation(event) {
         | 
| 407 418 | 
             
                    if (!event.tool_name) return 'unknown';
         | 
| 408 | 
            -
             | 
| 419 | 
            +
             | 
| 409 420 | 
             
                    const toolName = event.tool_name.toLowerCase();
         | 
| 410 421 | 
             
                    switch (toolName) {
         | 
| 411 422 | 
             
                        case 'read': return 'read';
         | 
| @@ -416,7 +427,7 @@ class FileToolTracker { | |
| 416 427 | 
             
                        case 'grep': return 'search';
         | 
| 417 428 | 
             
                        case 'glob': return 'search';
         | 
| 418 429 | 
             
                        case 'ls': return 'list';
         | 
| 419 | 
            -
                        case 'bash': | 
| 430 | 
            +
                        case 'bash':
         | 
| 420 431 | 
             
                            // Check bash command for file operation type
         | 
| 421 432 | 
             
                            const command = event.tool_parameters?.command || '';
         | 
| 422 433 | 
             
                            if (command.match(/\b(cat|less|more|head|tail)\b/)) return 'read';
         | 
| @@ -442,11 +453,11 @@ class FileToolTracker { | |
| 442 453 | 
             
                    if (pair.pre_event) {
         | 
| 443 454 | 
             
                        return this.getFileOperation(pair.pre_event);
         | 
| 444 455 | 
             
                    }
         | 
| 445 | 
            -
             | 
| 456 | 
            +
             | 
| 446 457 | 
             
                    if (pair.post_event) {
         | 
| 447 458 | 
             
                        return this.getFileOperation(pair.post_event);
         | 
| 448 459 | 
             
                    }
         | 
| 449 | 
            -
             | 
| 460 | 
            +
             | 
| 450 461 | 
             
                    return 'unknown';
         | 
| 451 462 | 
             
                }
         | 
| 452 463 |  | 
| @@ -467,11 +478,11 @@ class FileToolTracker { | |
| 467 478 | 
             
                            };
         | 
| 468 479 | 
             
                        }
         | 
| 469 480 | 
             
                    }
         | 
| 470 | 
            -
             | 
| 481 | 
            +
             | 
| 471 482 | 
             
                    // Fallback to direct event properties
         | 
| 472 | 
            -
                    const agentName = event?.agent_type || event?.subagent_type || | 
| 483 | 
            +
                    const agentName = event?.agent_type || event?.subagent_type ||
         | 
| 473 484 | 
             
                                      pair.pre_event?.agent_type || pair.post_event?.agent_type || 'PM';
         | 
| 474 | 
            -
             | 
| 485 | 
            +
             | 
| 475 486 | 
             
                    return {
         | 
| 476 487 | 
             
                        name: agentName,
         | 
| 477 488 | 
             
                        confidence: 'direct'
         | 
| @@ -485,14 +496,14 @@ class FileToolTracker { | |
| 485 496 | 
             
                 */
         | 
| 486 497 | 
             
                getFileOperationDetailsFromPair(pair) {
         | 
| 487 498 | 
             
                    const details = {};
         | 
| 488 | 
            -
             | 
| 499 | 
            +
             | 
| 489 500 | 
             
                    // Extract details from pre_event (parameters)
         | 
| 490 501 | 
             
                    if (pair.pre_event) {
         | 
| 491 502 | 
             
                        const params = pair.pre_event.tool_parameters || pair.pre_event.data?.tool_parameters || {};
         | 
| 492 503 | 
             
                        details.parameters = params;
         | 
| 493 504 | 
             
                        details.tool_input = pair.pre_event.tool_input;
         | 
| 494 505 | 
             
                    }
         | 
| 495 | 
            -
             | 
| 506 | 
            +
             | 
| 496 507 | 
             
                    // Extract details from post_event (results)
         | 
| 497 508 | 
             
                    if (pair.post_event) {
         | 
| 498 509 | 
             
                        details.result = pair.post_event.result;
         | 
| @@ -501,7 +512,7 @@ class FileToolTracker { | |
| 501 512 | 
             
                        details.exit_code = pair.post_event.exit_code;
         | 
| 502 513 | 
             
                        details.duration_ms = pair.post_event.duration_ms;
         | 
| 503 514 | 
             
                    }
         | 
| 504 | 
            -
             | 
| 515 | 
            +
             | 
| 505 516 | 
             
                    return details;
         | 
| 506 517 | 
             
                }
         | 
| 507 518 |  | 
| @@ -582,21 +593,21 @@ class FileToolTracker { | |
| 582 593 | 
             
                    // Extract parameters from both events
         | 
| 583 594 | 
             
                    const preParams = preEvent.tool_parameters || preEvent.data?.tool_parameters || {};
         | 
| 584 595 | 
             
                    const postParams = postEvent.tool_parameters || postEvent.data?.tool_parameters || {};
         | 
| 585 | 
            -
             | 
| 596 | 
            +
             | 
| 586 597 | 
             
                    // If no parameters in either event, can't compare meaningfully
         | 
| 587 598 | 
             
                    if (Object.keys(preParams).length === 0 && Object.keys(postParams).length === 0) {
         | 
| 588 599 | 
             
                        return false; // No boost for empty parameters
         | 
| 589 600 | 
             
                    }
         | 
| 590 | 
            -
             | 
| 601 | 
            +
             | 
| 591 602 | 
             
                    // Compare key parameters that are likely to be the same
         | 
| 592 603 | 
             
                    const importantParams = ['file_path', 'path', 'pattern', 'command', 'notebook_path'];
         | 
| 593 604 | 
             
                    let matchedParams = 0;
         | 
| 594 605 | 
             
                    let totalComparableParams = 0;
         | 
| 595 | 
            -
             | 
| 606 | 
            +
             | 
| 596 607 | 
             
                    importantParams.forEach(param => {
         | 
| 597 608 | 
             
                        const preValue = preParams[param];
         | 
| 598 609 | 
             
                        const postValue = postParams[param];
         | 
| 599 | 
            -
             | 
| 610 | 
            +
             | 
| 600 611 | 
             
                        if (preValue !== undefined || postValue !== undefined) {
         | 
| 601 612 | 
             
                            totalComparableParams++;
         | 
| 602 613 | 
             
                            if (preValue === postValue) {
         | 
| @@ -604,26 +615,26 @@ class FileToolTracker { | |
| 604 615 | 
             
                            }
         | 
| 605 616 | 
             
                        }
         | 
| 606 617 | 
             
                    });
         | 
| 607 | 
            -
             | 
| 618 | 
            +
             | 
| 608 619 | 
             
                    // If we found comparable parameters, check if most match
         | 
| 609 620 | 
             
                    if (totalComparableParams > 0) {
         | 
| 610 621 | 
             
                        return (matchedParams / totalComparableParams) >= 0.8; // 80% parameter match threshold
         | 
| 611 622 | 
             
                    }
         | 
| 612 | 
            -
             | 
| 623 | 
            +
             | 
| 613 624 | 
             
                    // If no important parameters to compare, check if the parameter structure is similar
         | 
| 614 625 | 
             
                    const preKeys = Object.keys(preParams).sort();
         | 
| 615 626 | 
             
                    const postKeys = Object.keys(postParams).sort();
         | 
| 616 | 
            -
             | 
| 627 | 
            +
             | 
| 617 628 | 
             
                    if (preKeys.length === 0 && postKeys.length === 0) {
         | 
| 618 629 | 
             
                        return false;
         | 
| 619 630 | 
             
                    }
         | 
| 620 | 
            -
             | 
| 631 | 
            +
             | 
| 621 632 | 
             
                    // Simple structural similarity check
         | 
| 622 633 | 
             
                    if (preKeys.length === postKeys.length) {
         | 
| 623 634 | 
             
                        const keyMatches = preKeys.filter(key => postKeys.includes(key)).length;
         | 
| 624 635 | 
             
                        return keyMatches >= Math.max(1, preKeys.length * 0.5); // At least 50% key overlap
         | 
| 625 636 | 
             
                    }
         | 
| 626 | 
            -
             | 
| 637 | 
            +
             | 
| 627 638 | 
             
                    return false;
         | 
| 628 639 | 
             
                }
         | 
| 629 640 |  | 
| @@ -642,14 +653,17 @@ class FileToolTracker { | |
| 642 653 | 
             
                            };
         | 
| 643 654 | 
             
                        }
         | 
| 644 655 | 
             
                    }
         | 
| 645 | 
            -
             | 
| 656 | 
            +
             | 
| 646 657 | 
             
                    // Fallback to direct event properties
         | 
| 647 | 
            -
                    const agentName = event.agent_type || event.subagent_type || | 
| 658 | 
            +
                    const agentName = event.agent_type || event.subagent_type ||
         | 
| 648 659 | 
             
                                      event.data?.agent_type || event.data?.subagent_type || 'PM';
         | 
| 649 | 
            -
             | 
| 660 | 
            +
             | 
| 650 661 | 
             
                    return {
         | 
| 651 662 | 
             
                        name: agentName,
         | 
| 652 663 | 
             
                        confidence: 'direct'
         | 
| 653 664 | 
             
                    };
         | 
| 654 665 | 
             
                }
         | 
| 655 | 
            -
            }
         | 
| 666 | 
            +
            }
         | 
| 667 | 
            +
            // ES6 Module export
         | 
| 668 | 
            +
            export { FileToolTracker };
         | 
| 669 | 
            +
            export default FileToolTracker;
         | 
| @@ -8,7 +8,7 @@ class HUDLibraryLoader { | |
| 8 8 | 
             
                    this.loadedLibraries = new Set();
         | 
| 9 9 | 
             
                    this.loadingPromises = new Map();
         | 
| 10 10 | 
             
                    this.loadingCallbacks = new Map();
         | 
| 11 | 
            -
             | 
| 11 | 
            +
             | 
| 12 12 | 
             
                    // Define library configurations with proper loading order
         | 
| 13 13 | 
             
                    this.libraries = [
         | 
| 14 14 | 
             
                        {
         | 
| @@ -55,7 +55,7 @@ class HUDLibraryLoader { | |
| 55 55 | 
             
                        const script = document.createElement('script');
         | 
| 56 56 | 
             
                        script.src = library.url;
         | 
| 57 57 | 
             
                        script.async = true;
         | 
| 58 | 
            -
             | 
| 58 | 
            +
             | 
| 59 59 | 
             
                        script.onload = () => {
         | 
| 60 60 | 
             
                            if (library.globalCheck()) {
         | 
| 61 61 | 
             
                                console.log(`Successfully loaded library: ${library.name}`);
         | 
| @@ -69,14 +69,14 @@ class HUDLibraryLoader { | |
| 69 69 | 
             
                                reject(error);
         | 
| 70 70 | 
             
                            }
         | 
| 71 71 | 
             
                        };
         | 
| 72 | 
            -
             | 
| 72 | 
            +
             | 
| 73 73 | 
             
                        script.onerror = () => {
         | 
| 74 74 | 
             
                            const error = new Error(`Failed to load library: ${library.name} from ${library.url}`);
         | 
| 75 75 | 
             
                            console.error(error);
         | 
| 76 76 | 
             
                            this.loadingPromises.delete(library.name);
         | 
| 77 77 | 
             
                            reject(error);
         | 
| 78 78 | 
             
                        };
         | 
| 79 | 
            -
             | 
| 79 | 
            +
             | 
| 80 80 | 
             
                        document.head.appendChild(script);
         | 
| 81 81 | 
             
                    });
         | 
| 82 82 |  | 
| @@ -123,12 +123,12 @@ class HUDLibraryLoader { | |
| 123 123 | 
             
                 */
         | 
| 124 124 | 
             
                async loadHUDLibraries(onProgress = null) {
         | 
| 125 125 | 
             
                    console.log('Starting HUD libraries loading...');
         | 
| 126 | 
            -
             | 
| 126 | 
            +
             | 
| 127 127 | 
             
                    try {
         | 
| 128 128 | 
             
                        // Load libraries in dependency order
         | 
| 129 129 | 
             
                        for (let i = 0; i < this.libraries.length; i++) {
         | 
| 130 130 | 
             
                            const library = this.libraries[i];
         | 
| 131 | 
            -
             | 
| 131 | 
            +
             | 
| 132 132 | 
             
                            if (onProgress) {
         | 
| 133 133 | 
             
                                onProgress({
         | 
| 134 134 | 
             
                                    library: library.name,
         | 
| @@ -137,7 +137,7 @@ class HUDLibraryLoader { | |
| 137 137 | 
             
                                    message: `Loading ${library.name}...`
         | 
| 138 138 | 
             
                                });
         | 
| 139 139 | 
             
                            }
         | 
| 140 | 
            -
             | 
| 140 | 
            +
             | 
| 141 141 | 
             
                            await this.loadLibraryWithDependencies(library);
         | 
| 142 142 | 
             
                        }
         | 
| 143 143 |  | 
| @@ -148,7 +148,7 @@ class HUDLibraryLoader { | |
| 148 148 | 
             
                        }
         | 
| 149 149 |  | 
| 150 150 | 
             
                        console.log('All HUD libraries loaded successfully');
         | 
| 151 | 
            -
             | 
| 151 | 
            +
             | 
| 152 152 | 
             
                        if (onProgress) {
         | 
| 153 153 | 
             
                            onProgress({
         | 
| 154 154 | 
             
                                library: 'complete',
         | 
| @@ -161,7 +161,7 @@ class HUDLibraryLoader { | |
| 161 161 | 
             
                        return true;
         | 
| 162 162 | 
             
                    } catch (error) {
         | 
| 163 163 | 
             
                        console.error('Failed to load HUD libraries:', error);
         | 
| 164 | 
            -
             | 
| 164 | 
            +
             | 
| 165 165 | 
             
                        if (onProgress) {
         | 
| 166 166 | 
             
                            onProgress({
         | 
| 167 167 | 
             
                                library: 'error',
         | 
| @@ -171,7 +171,7 @@ class HUDLibraryLoader { | |
| 171 171 | 
             
                                error: error
         | 
| 172 172 | 
             
                            });
         | 
| 173 173 | 
             
                        }
         | 
| 174 | 
            -
             | 
| 174 | 
            +
             | 
| 175 175 | 
             
                        throw error;
         | 
| 176 176 | 
             
                    }
         | 
| 177 177 | 
             
                }
         | 
| @@ -208,4 +208,4 @@ class HUDLibraryLoader { | |
| 208 208 | 
             
            }
         | 
| 209 209 |  | 
| 210 210 | 
             
            // Create singleton instance
         | 
| 211 | 
            -
            window.HUDLibraryLoader = new HUDLibraryLoader();
         | 
| 211 | 
            +
            window.HUDLibraryLoader = new HUDLibraryLoader();
         |