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,549 @@ | |
| 1 | 
            +
            #!/usr/bin/env python3
         | 
| 2 | 
            +
            """
         | 
| 3 | 
            +
            Unified Path Management System for Claude MPM
         | 
| 4 | 
            +
            ==============================================
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            This module consolidates all path management functionality from the duplicate modules:
         | 
| 7 | 
            +
            - config/paths.py (ClaudeMPMPaths)
         | 
| 8 | 
            +
            - utils/paths.py (get_path_manager())
         | 
| 9 | 
            +
            - deployment_paths.py (get_path_manager())
         | 
| 10 | 
            +
            - core/config_paths.py (get_path_manager())
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Design Principles:
         | 
| 13 | 
            +
            - Single source of truth for all path operations
         | 
| 14 | 
            +
            - Consistent API across all path types
         | 
| 15 | 
            +
            - Robust deployment scenario handling
         | 
| 16 | 
            +
            - Efficient caching with cache invalidation
         | 
| 17 | 
            +
            - Clear separation of concerns
         | 
| 18 | 
            +
            - Backward compatibility during migration
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            Architecture:
         | 
| 21 | 
            +
            - UnifiedPathManager: Main singleton class
         | 
| 22 | 
            +
            - PathType enum: Categorizes different path types
         | 
| 23 | 
            +
            - PathContext: Handles deployment context detection
         | 
| 24 | 
            +
            - Cached properties with smart invalidation
         | 
| 25 | 
            +
            """
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            import logging
         | 
| 28 | 
            +
            import os
         | 
| 29 | 
            +
            import sys
         | 
| 30 | 
            +
            from enum import Enum
         | 
| 31 | 
            +
            from functools import lru_cache
         | 
| 32 | 
            +
            from pathlib import Path
         | 
| 33 | 
            +
            from typing import Dict, List, Optional, Union
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            logger = logging.getLogger(__name__)
         | 
| 36 | 
            +
             | 
| 37 | 
            +
             | 
| 38 | 
            +
            class PathType(Enum):
         | 
| 39 | 
            +
                """Enumeration of different path types for categorization."""
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                PROJECT = "project"
         | 
| 42 | 
            +
                FRAMEWORK = "framework"
         | 
| 43 | 
            +
                USER = "user"
         | 
| 44 | 
            +
                SYSTEM = "system"
         | 
| 45 | 
            +
                CONFIG = "config"
         | 
| 46 | 
            +
                AGENTS = "agents"
         | 
| 47 | 
            +
                TEMPLATES = "templates"
         | 
| 48 | 
            +
                SCRIPTS = "scripts"
         | 
| 49 | 
            +
                STATIC = "static"
         | 
| 50 | 
            +
                LOGS = "logs"
         | 
| 51 | 
            +
                CACHE = "cache"
         | 
| 52 | 
            +
             | 
| 53 | 
            +
             | 
| 54 | 
            +
            class DeploymentContext(Enum):
         | 
| 55 | 
            +
                """Enumeration of deployment contexts."""
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                DEVELOPMENT = "development"
         | 
| 58 | 
            +
                EDITABLE_INSTALL = "editable_install"
         | 
| 59 | 
            +
                PIP_INSTALL = "pip_install"
         | 
| 60 | 
            +
                PIPX_INSTALL = "pipx_install"
         | 
| 61 | 
            +
                SYSTEM_PACKAGE = "system_package"
         | 
| 62 | 
            +
             | 
| 63 | 
            +
             | 
| 64 | 
            +
            class PathContext:
         | 
| 65 | 
            +
                """Handles deployment context detection and path resolution."""
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                @staticmethod
         | 
| 68 | 
            +
                @lru_cache(maxsize=1)
         | 
| 69 | 
            +
                def detect_deployment_context() -> DeploymentContext:
         | 
| 70 | 
            +
                    """Detect the current deployment context."""
         | 
| 71 | 
            +
                    try:
         | 
| 72 | 
            +
                        import claude_mpm
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                        module_path = Path(claude_mpm.__file__).parent
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                        # Check for development mode
         | 
| 77 | 
            +
                        if (module_path.parent / "src").exists():
         | 
| 78 | 
            +
                            return DeploymentContext.DEVELOPMENT
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                        # Check for editable install
         | 
| 81 | 
            +
                        if (
         | 
| 82 | 
            +
                            "site-packages" in str(module_path)
         | 
| 83 | 
            +
                            and (module_path.parent.parent / "src").exists()
         | 
| 84 | 
            +
                        ):
         | 
| 85 | 
            +
                            return DeploymentContext.EDITABLE_INSTALL
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                        # Check for pipx install
         | 
| 88 | 
            +
                        if "pipx" in str(module_path):
         | 
| 89 | 
            +
                            return DeploymentContext.PIPX_INSTALL
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                        # Check for system package
         | 
| 92 | 
            +
                        if "dist-packages" in str(module_path):
         | 
| 93 | 
            +
                            return DeploymentContext.SYSTEM_PACKAGE
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                        # Default to pip install
         | 
| 96 | 
            +
                        return DeploymentContext.PIP_INSTALL
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    except ImportError:
         | 
| 99 | 
            +
                        return DeploymentContext.DEVELOPMENT
         | 
| 100 | 
            +
             | 
| 101 | 
            +
             | 
| 102 | 
            +
            class UnifiedPathManager:
         | 
| 103 | 
            +
                """
         | 
| 104 | 
            +
                Unified path management system that consolidates all path-related functionality.
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                This class provides a single, authoritative interface for all path operations
         | 
| 107 | 
            +
                in Claude MPM, replacing the multiple duplicate path management modules.
         | 
| 108 | 
            +
                """
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                _instance: Optional["UnifiedPathManager"] = None
         | 
| 111 | 
            +
                _cache_invalidated: bool = False
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                # Configuration constants
         | 
| 114 | 
            +
                CONFIG_DIR_NAME = ".claude-mpm"
         | 
| 115 | 
            +
                LEGACY_CONFIG_DIR_NAME = ".claude-pm"  # For migration support
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                def __new__(cls) -> "UnifiedPathManager":
         | 
| 118 | 
            +
                    """Singleton pattern to ensure single instance."""
         | 
| 119 | 
            +
                    if cls._instance is None:
         | 
| 120 | 
            +
                        cls._instance = super().__new__(cls)
         | 
| 121 | 
            +
                        cls._instance._initialized = False
         | 
| 122 | 
            +
                    return cls._instance
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                def __init__(self):
         | 
| 125 | 
            +
                    """Initialize the path manager."""
         | 
| 126 | 
            +
                    if self._initialized:
         | 
| 127 | 
            +
                        return
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                    self._deployment_context = PathContext.detect_deployment_context()
         | 
| 130 | 
            +
                    self._project_markers = [
         | 
| 131 | 
            +
                        ".git",
         | 
| 132 | 
            +
                        "pyproject.toml",
         | 
| 133 | 
            +
                        "package.json",
         | 
| 134 | 
            +
                        "Cargo.toml",
         | 
| 135 | 
            +
                        "go.mod",
         | 
| 136 | 
            +
                        "pom.xml",
         | 
| 137 | 
            +
                        "build.gradle",
         | 
| 138 | 
            +
                        self.CONFIG_DIR_NAME,
         | 
| 139 | 
            +
                    ]
         | 
| 140 | 
            +
                    self._initialized = True
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                    logger.debug(
         | 
| 143 | 
            +
                        f"UnifiedPathManager initialized with context: {self._deployment_context}"
         | 
| 144 | 
            +
                    )
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                # ========================================================================
         | 
| 147 | 
            +
                # Core Path Resolution Methods
         | 
| 148 | 
            +
                # ========================================================================
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                @property
         | 
| 151 | 
            +
                @lru_cache(maxsize=1)
         | 
| 152 | 
            +
                def framework_root(self) -> Path:
         | 
| 153 | 
            +
                    """Get the framework root directory."""
         | 
| 154 | 
            +
                    try:
         | 
| 155 | 
            +
                        import claude_mpm
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                        module_path = Path(claude_mpm.__file__).parent
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                        if self._deployment_context == DeploymentContext.DEVELOPMENT:
         | 
| 160 | 
            +
                            # Development: go up to project root
         | 
| 161 | 
            +
                            current = module_path
         | 
| 162 | 
            +
                            while current != current.parent:
         | 
| 163 | 
            +
                                if (current / "src" / "claude_mpm").exists():
         | 
| 164 | 
            +
                                    return current
         | 
| 165 | 
            +
                                current = current.parent
         | 
| 166 | 
            +
             | 
| 167 | 
            +
                        # For installed packages, the module path is the framework root
         | 
| 168 | 
            +
                        return (
         | 
| 169 | 
            +
                            module_path.parent if module_path.name == "claude_mpm" else module_path
         | 
| 170 | 
            +
                        )
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                    except ImportError:
         | 
| 173 | 
            +
                        # Fallback: search from current file location
         | 
| 174 | 
            +
                        current = Path(__file__).parent
         | 
| 175 | 
            +
                        while current != current.parent:
         | 
| 176 | 
            +
                            if (current / "src" / "claude_mpm").exists():
         | 
| 177 | 
            +
                                return current
         | 
| 178 | 
            +
                            current = current.parent
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                        raise FileNotFoundError("Could not determine framework root")
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                @property
         | 
| 183 | 
            +
                @lru_cache(maxsize=1)
         | 
| 184 | 
            +
                def project_root(self) -> Path:
         | 
| 185 | 
            +
                    """Get the current project root directory."""
         | 
| 186 | 
            +
                    current = Path.cwd()
         | 
| 187 | 
            +
                    while current != current.parent:
         | 
| 188 | 
            +
                        for marker in self._project_markers:
         | 
| 189 | 
            +
                            if (current / marker).exists():
         | 
| 190 | 
            +
                                logger.debug(f"Found project root at {current} via {marker}")
         | 
| 191 | 
            +
                                return current
         | 
| 192 | 
            +
                        current = current.parent
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                    # Fallback to current directory
         | 
| 195 | 
            +
                    logger.warning("Could not find project root, using current directory")
         | 
| 196 | 
            +
                    return Path.cwd()
         | 
| 197 | 
            +
             | 
| 198 | 
            +
                @property
         | 
| 199 | 
            +
                def package_root(self) -> Path:
         | 
| 200 | 
            +
                    """Get the claude_mpm package root directory."""
         | 
| 201 | 
            +
                    try:
         | 
| 202 | 
            +
                        import claude_mpm
         | 
| 203 | 
            +
             | 
| 204 | 
            +
                        return Path(claude_mpm.__file__).parent
         | 
| 205 | 
            +
                    except ImportError:
         | 
| 206 | 
            +
                        return self.framework_root / "src" / "claude_mpm"
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                # ========================================================================
         | 
| 209 | 
            +
                # Configuration Paths
         | 
| 210 | 
            +
                # ========================================================================
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                def get_config_dir(self, scope: str = "project") -> Path:
         | 
| 213 | 
            +
                    """Get configuration directory for specified scope."""
         | 
| 214 | 
            +
                    if scope == "user":
         | 
| 215 | 
            +
                        return Path.home() / self.CONFIG_DIR_NAME
         | 
| 216 | 
            +
                    elif scope == "project":
         | 
| 217 | 
            +
                        return self.project_root / self.CONFIG_DIR_NAME
         | 
| 218 | 
            +
                    elif scope == "framework":
         | 
| 219 | 
            +
                        return self.framework_root / self.CONFIG_DIR_NAME
         | 
| 220 | 
            +
                    else:
         | 
| 221 | 
            +
                        raise ValueError(
         | 
| 222 | 
            +
                            f"Invalid scope: {scope}. Must be 'user', 'project', or 'framework'"
         | 
| 223 | 
            +
                        )
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                def get_user_config_dir(self) -> Path:
         | 
| 226 | 
            +
                    """Get the user-level configuration directory."""
         | 
| 227 | 
            +
                    return Path.home() / self.CONFIG_DIR_NAME
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                def get_project_config_dir(self, project_root: Optional[Path] = None) -> Path:
         | 
| 230 | 
            +
                    """Get the project-level configuration directory."""
         | 
| 231 | 
            +
                    root = project_root or self.project_root
         | 
| 232 | 
            +
                    return root / self.CONFIG_DIR_NAME
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                # ========================================================================
         | 
| 235 | 
            +
                # Agent Paths
         | 
| 236 | 
            +
                # ========================================================================
         | 
| 237 | 
            +
             | 
| 238 | 
            +
                def get_agents_dir(self, scope: str = "framework") -> Path:
         | 
| 239 | 
            +
                    """Get agents directory for specified scope."""
         | 
| 240 | 
            +
                    if scope == "user":
         | 
| 241 | 
            +
                        return self.get_user_config_dir() / "agents"
         | 
| 242 | 
            +
                    elif scope == "project":
         | 
| 243 | 
            +
                        return self.get_project_config_dir() / "agents"
         | 
| 244 | 
            +
                    elif scope == "framework":
         | 
| 245 | 
            +
                        if self._deployment_context == DeploymentContext.DEVELOPMENT:
         | 
| 246 | 
            +
                            return self.framework_root / "src" / "claude_mpm" / "agents"
         | 
| 247 | 
            +
                        else:
         | 
| 248 | 
            +
                            return self.package_root / "agents"
         | 
| 249 | 
            +
                    else:
         | 
| 250 | 
            +
                        raise ValueError(
         | 
| 251 | 
            +
                            f"Invalid scope: {scope}. Must be 'user', 'project', or 'framework'"
         | 
| 252 | 
            +
                        )
         | 
| 253 | 
            +
             | 
| 254 | 
            +
                def get_user_agents_dir(self) -> Path:
         | 
| 255 | 
            +
                    """Get the user-level agents directory."""
         | 
| 256 | 
            +
                    return self.get_user_config_dir() / "agents"
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                def get_project_agents_dir(self, project_root: Optional[Path] = None) -> Path:
         | 
| 259 | 
            +
                    """Get the project-level agents directory."""
         | 
| 260 | 
            +
                    return self.get_project_config_dir(project_root) / "agents"
         | 
| 261 | 
            +
             | 
| 262 | 
            +
                def get_system_agents_dir(self) -> Path:
         | 
| 263 | 
            +
                    """Get the system-level agents directory."""
         | 
| 264 | 
            +
                    return self.get_agents_dir("framework")
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                def get_templates_dir(self) -> Path:
         | 
| 267 | 
            +
                    """Get the agent templates directory."""
         | 
| 268 | 
            +
                    return self.get_agents_dir("framework") / "templates"
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                # ========================================================================
         | 
| 271 | 
            +
                # Resource and Static Paths
         | 
| 272 | 
            +
                # ========================================================================
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                def get_scripts_dir(self) -> Path:
         | 
| 275 | 
            +
                    """Get the scripts directory."""
         | 
| 276 | 
            +
                    if self._deployment_context == DeploymentContext.DEVELOPMENT:
         | 
| 277 | 
            +
                        return self.framework_root / "scripts"
         | 
| 278 | 
            +
                    else:
         | 
| 279 | 
            +
                        return self.package_root / "scripts"
         | 
| 280 | 
            +
             | 
| 281 | 
            +
                def get_static_dir(self) -> Path:
         | 
| 282 | 
            +
                    """Get the static files directory."""
         | 
| 283 | 
            +
                    return self.package_root / "dashboard" / "static"
         | 
| 284 | 
            +
             | 
| 285 | 
            +
                def get_templates_web_dir(self) -> Path:
         | 
| 286 | 
            +
                    """Get the web templates directory."""
         | 
| 287 | 
            +
                    return self.package_root / "dashboard" / "templates"
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                # ========================================================================
         | 
| 290 | 
            +
                # Utility and Working Paths
         | 
| 291 | 
            +
                # ========================================================================
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                def get_logs_dir(self, scope: str = "project") -> Path:
         | 
| 294 | 
            +
                    """Get logs directory for specified scope."""
         | 
| 295 | 
            +
                    base_dir = self.get_config_dir(scope)
         | 
| 296 | 
            +
                    return base_dir / "logs"
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                def get_cache_dir(self, scope: str = "user") -> Path:
         | 
| 299 | 
            +
                    """Get cache directory for specified scope."""
         | 
| 300 | 
            +
                    base_dir = self.get_config_dir(scope)
         | 
| 301 | 
            +
                    return base_dir / "cache"
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                def get_backups_dir(self, scope: str = "user") -> Path:
         | 
| 304 | 
            +
                    """Get backups directory for specified scope."""
         | 
| 305 | 
            +
                    base_dir = self.get_config_dir(scope)
         | 
| 306 | 
            +
                    return base_dir / "backups"
         | 
| 307 | 
            +
             | 
| 308 | 
            +
                def get_memories_dir(self, scope: str = "project") -> Path:
         | 
| 309 | 
            +
                    """Get memories directory for specified scope."""
         | 
| 310 | 
            +
                    base_dir = self.get_config_dir(scope)
         | 
| 311 | 
            +
                    return base_dir / "memories"
         | 
| 312 | 
            +
             | 
| 313 | 
            +
                # ========================================================================
         | 
| 314 | 
            +
                # File Path Resolution
         | 
| 315 | 
            +
                # ========================================================================
         | 
| 316 | 
            +
             | 
| 317 | 
            +
                def get_resource_path(self, resource_type: str, filename: str) -> Path:
         | 
| 318 | 
            +
                    """Get path to a resource file."""
         | 
| 319 | 
            +
                    resource_dirs = {
         | 
| 320 | 
            +
                        "scripts": self.get_scripts_dir(),
         | 
| 321 | 
            +
                        "templates": self.get_templates_dir(),
         | 
| 322 | 
            +
                        "static": self.get_static_dir(),
         | 
| 323 | 
            +
                        "agents": self.get_agents_dir("framework"),
         | 
| 324 | 
            +
                        "web_templates": self.get_templates_web_dir(),
         | 
| 325 | 
            +
                    }
         | 
| 326 | 
            +
             | 
| 327 | 
            +
                    base_dir = resource_dirs.get(resource_type, self.package_root)
         | 
| 328 | 
            +
                    return base_dir / filename
         | 
| 329 | 
            +
             | 
| 330 | 
            +
                def find_file_upwards(
         | 
| 331 | 
            +
                    self, filename: str, start_path: Optional[Path] = None
         | 
| 332 | 
            +
                ) -> Optional[Path]:
         | 
| 333 | 
            +
                    """Search for a file by traversing up the directory tree."""
         | 
| 334 | 
            +
                    current = start_path or Path.cwd()
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                    while current != current.parent:
         | 
| 337 | 
            +
                        candidate = current / filename
         | 
| 338 | 
            +
                        if candidate.exists():
         | 
| 339 | 
            +
                            return candidate
         | 
| 340 | 
            +
                        current = current.parent
         | 
| 341 | 
            +
             | 
| 342 | 
            +
                    return None
         | 
| 343 | 
            +
             | 
| 344 | 
            +
                def get_package_resource_path(self, resource_path: str) -> Path:
         | 
| 345 | 
            +
                    """Get the path to a resource within the claude_mpm package."""
         | 
| 346 | 
            +
                    # Try using importlib.resources for proper package resource access
         | 
| 347 | 
            +
                    try:
         | 
| 348 | 
            +
                        from importlib import resources
         | 
| 349 | 
            +
             | 
| 350 | 
            +
                        parts = resource_path.split("/")
         | 
| 351 | 
            +
                        if len(parts) == 1:
         | 
| 352 | 
            +
                            with resources.path("claude_mpm", parts[0]) as p:
         | 
| 353 | 
            +
                                if p.exists():
         | 
| 354 | 
            +
                                    return p
         | 
| 355 | 
            +
                        else:
         | 
| 356 | 
            +
                            # For nested paths, navigate step by step
         | 
| 357 | 
            +
                            package = "claude_mpm"
         | 
| 358 | 
            +
                            for part in parts[:-1]:
         | 
| 359 | 
            +
                                package = f"{package}.{part}"
         | 
| 360 | 
            +
                            with resources.path(package, parts[-1]) as p:
         | 
| 361 | 
            +
                                if p.exists():
         | 
| 362 | 
            +
                                    return p
         | 
| 363 | 
            +
                    except (ImportError, ModuleNotFoundError, TypeError, AttributeError):
         | 
| 364 | 
            +
                        # Fall back to file system detection
         | 
| 365 | 
            +
                        pass
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                    # Fallback: Use package root
         | 
| 368 | 
            +
                    resource = self.package_root / resource_path
         | 
| 369 | 
            +
                    if resource.exists():
         | 
| 370 | 
            +
                        return resource
         | 
| 371 | 
            +
             | 
| 372 | 
            +
                    raise FileNotFoundError(f"Resource not found: {resource_path}")
         | 
| 373 | 
            +
             | 
| 374 | 
            +
                # ========================================================================
         | 
| 375 | 
            +
                # Path Validation and Utilities
         | 
| 376 | 
            +
                # ========================================================================
         | 
| 377 | 
            +
             | 
| 378 | 
            +
                def ensure_directory(self, path: Path) -> Path:
         | 
| 379 | 
            +
                    """Ensure a directory exists, creating it if necessary."""
         | 
| 380 | 
            +
                    path.mkdir(parents=True, exist_ok=True)
         | 
| 381 | 
            +
                    return path
         | 
| 382 | 
            +
             | 
| 383 | 
            +
                def validate_not_legacy(self, path: Path) -> bool:
         | 
| 384 | 
            +
                    """Check if a path contains the legacy configuration directory name."""
         | 
| 385 | 
            +
                    return self.LEGACY_CONFIG_DIR_NAME not in str(path)
         | 
| 386 | 
            +
             | 
| 387 | 
            +
                def get_relative_to_root(
         | 
| 388 | 
            +
                    self, path: Union[str, Path], root_type: str = "project"
         | 
| 389 | 
            +
                ) -> Path:
         | 
| 390 | 
            +
                    """Get a path relative to a specific root."""
         | 
| 391 | 
            +
                    if root_type == "project":
         | 
| 392 | 
            +
                        root = self.project_root
         | 
| 393 | 
            +
                    elif root_type == "framework":
         | 
| 394 | 
            +
                        root = self.framework_root
         | 
| 395 | 
            +
                    else:
         | 
| 396 | 
            +
                        raise ValueError(
         | 
| 397 | 
            +
                            f"Invalid root_type: {root_type}. Must be 'project' or 'framework'"
         | 
| 398 | 
            +
                        )
         | 
| 399 | 
            +
             | 
| 400 | 
            +
                    return root / path
         | 
| 401 | 
            +
             | 
| 402 | 
            +
                def resolve_import_path(self, module_path: str) -> Path:
         | 
| 403 | 
            +
                    """Resolve a module import path to a file path."""
         | 
| 404 | 
            +
                    parts = module_path.split(".")
         | 
| 405 | 
            +
                    if parts[0] == "claude_mpm":
         | 
| 406 | 
            +
                        parts = parts[1:]  # Remove package name
         | 
| 407 | 
            +
             | 
| 408 | 
            +
                    return self.package_root.joinpath(*parts).with_suffix(".py")
         | 
| 409 | 
            +
             | 
| 410 | 
            +
                # ========================================================================
         | 
| 411 | 
            +
                # Cache Management
         | 
| 412 | 
            +
                # ========================================================================
         | 
| 413 | 
            +
             | 
| 414 | 
            +
                def clear_cache(self):
         | 
| 415 | 
            +
                    """Clear all cached path lookups."""
         | 
| 416 | 
            +
                    # Clear lru_cache instances
         | 
| 417 | 
            +
                    try:
         | 
| 418 | 
            +
                        # Clear property caches if they exist
         | 
| 419 | 
            +
                        if hasattr(type(self).framework_root, "fget") and hasattr(
         | 
| 420 | 
            +
                            type(self).framework_root.fget, "cache_clear"
         | 
| 421 | 
            +
                        ):
         | 
| 422 | 
            +
                            type(self).framework_root.fget.cache_clear()
         | 
| 423 | 
            +
                        if hasattr(type(self).project_root, "fget") and hasattr(
         | 
| 424 | 
            +
                            type(self).project_root.fget, "cache_clear"
         | 
| 425 | 
            +
                        ):
         | 
| 426 | 
            +
                            type(self).project_root.fget.cache_clear()
         | 
| 427 | 
            +
                    except AttributeError:
         | 
| 428 | 
            +
                        # Properties might not have cache_clear if not using lru_cache
         | 
| 429 | 
            +
                        pass
         | 
| 430 | 
            +
             | 
| 431 | 
            +
                    # Clear static method cache
         | 
| 432 | 
            +
                    PathContext.detect_deployment_context.cache_clear()
         | 
| 433 | 
            +
             | 
| 434 | 
            +
                    logger.debug("Cleared all UnifiedPathManager caches")
         | 
| 435 | 
            +
             | 
| 436 | 
            +
                def invalidate_cache(self):
         | 
| 437 | 
            +
                    """Mark cache as invalidated for next access."""
         | 
| 438 | 
            +
                    self._cache_invalidated = True
         | 
| 439 | 
            +
                    self.clear_cache()
         | 
| 440 | 
            +
             | 
| 441 | 
            +
                # ========================================================================
         | 
| 442 | 
            +
                # Legacy Compatibility Methods
         | 
| 443 | 
            +
                # ========================================================================
         | 
| 444 | 
            +
             | 
| 445 | 
            +
                def get_version(self) -> str:
         | 
| 446 | 
            +
                    """Get the project version."""
         | 
| 447 | 
            +
                    version_candidates = [
         | 
| 448 | 
            +
                        self.framework_root / "VERSION",
         | 
| 449 | 
            +
                        self.package_root / "VERSION",
         | 
| 450 | 
            +
                        self.project_root / "VERSION",
         | 
| 451 | 
            +
                    ]
         | 
| 452 | 
            +
             | 
| 453 | 
            +
                    for version_file in version_candidates:
         | 
| 454 | 
            +
                        if version_file.exists():
         | 
| 455 | 
            +
                            return version_file.read_text().strip()
         | 
| 456 | 
            +
             | 
| 457 | 
            +
                    # Fallback to package metadata
         | 
| 458 | 
            +
                    try:
         | 
| 459 | 
            +
                        import claude_mpm
         | 
| 460 | 
            +
             | 
| 461 | 
            +
                        return getattr(claude_mpm, "__version__", "unknown")
         | 
| 462 | 
            +
                    except (ImportError, AttributeError):
         | 
| 463 | 
            +
                        return "unknown"
         | 
| 464 | 
            +
             | 
| 465 | 
            +
                def ensure_src_in_path(self):
         | 
| 466 | 
            +
                    """Ensure src directory is in Python path."""
         | 
| 467 | 
            +
                    src_dir = self.framework_root / "src"
         | 
| 468 | 
            +
                    if src_dir.exists() and str(src_dir) not in sys.path:
         | 
| 469 | 
            +
                        sys.path.insert(0, str(src_dir))
         | 
| 470 | 
            +
             | 
| 471 | 
            +
             | 
| 472 | 
            +
            # ============================================================================
         | 
| 473 | 
            +
            # Singleton Instance and Convenience Functions
         | 
| 474 | 
            +
            # ============================================================================
         | 
| 475 | 
            +
             | 
| 476 | 
            +
            # Global singleton instance
         | 
| 477 | 
            +
            _path_manager: Optional[UnifiedPathManager] = None
         | 
| 478 | 
            +
             | 
| 479 | 
            +
             | 
| 480 | 
            +
            def get_path_manager() -> UnifiedPathManager:
         | 
| 481 | 
            +
                """Get the global UnifiedPathManager instance."""
         | 
| 482 | 
            +
                global _path_manager
         | 
| 483 | 
            +
                if _path_manager is None:
         | 
| 484 | 
            +
                    _path_manager = UnifiedPathManager()
         | 
| 485 | 
            +
                return _path_manager
         | 
| 486 | 
            +
             | 
| 487 | 
            +
             | 
| 488 | 
            +
            # Convenience functions for backward compatibility
         | 
| 489 | 
            +
            def get_project_root() -> Path:
         | 
| 490 | 
            +
                """Get the current project root directory."""
         | 
| 491 | 
            +
                return get_path_manager().project_root
         | 
| 492 | 
            +
             | 
| 493 | 
            +
             | 
| 494 | 
            +
            def get_framework_root() -> Path:
         | 
| 495 | 
            +
                """Get the framework root directory."""
         | 
| 496 | 
            +
                return get_path_manager().framework_root
         | 
| 497 | 
            +
             | 
| 498 | 
            +
             | 
| 499 | 
            +
            def get_package_root() -> Path:
         | 
| 500 | 
            +
                """Get the claude_mpm package root directory."""
         | 
| 501 | 
            +
                return get_path_manager().package_root
         | 
| 502 | 
            +
             | 
| 503 | 
            +
             | 
| 504 | 
            +
            def get_scripts_dir() -> Path:
         | 
| 505 | 
            +
                """Get the scripts directory."""
         | 
| 506 | 
            +
                return get_path_manager().get_scripts_dir()
         | 
| 507 | 
            +
             | 
| 508 | 
            +
             | 
| 509 | 
            +
            def get_agents_dir() -> Path:
         | 
| 510 | 
            +
                """Get the framework agents directory."""
         | 
| 511 | 
            +
                return get_path_manager().get_agents_dir("framework")
         | 
| 512 | 
            +
             | 
| 513 | 
            +
             | 
| 514 | 
            +
            def get_config_dir(scope: str = "project") -> Path:
         | 
| 515 | 
            +
                """Get configuration directory for specified scope."""
         | 
| 516 | 
            +
                return get_path_manager().get_config_dir(scope)
         | 
| 517 | 
            +
             | 
| 518 | 
            +
             | 
| 519 | 
            +
            def find_file_upwards(
         | 
| 520 | 
            +
                filename: str, start_path: Optional[Path] = None
         | 
| 521 | 
            +
            ) -> Optional[Path]:
         | 
| 522 | 
            +
                """Search for a file by traversing up the directory tree."""
         | 
| 523 | 
            +
                return get_path_manager().find_file_upwards(filename, start_path)
         | 
| 524 | 
            +
             | 
| 525 | 
            +
             | 
| 526 | 
            +
            def get_package_resource_path(resource_path: str) -> Path:
         | 
| 527 | 
            +
                """Get the path to a resource within the claude_mpm package."""
         | 
| 528 | 
            +
                return get_path_manager().get_package_resource_path(resource_path)
         | 
| 529 | 
            +
             | 
| 530 | 
            +
             | 
| 531 | 
            +
            # ============================================================================
         | 
| 532 | 
            +
            # Export All Public Symbols
         | 
| 533 | 
            +
            # ============================================================================
         | 
| 534 | 
            +
             | 
| 535 | 
            +
            __all__ = [
         | 
| 536 | 
            +
                "UnifiedPathManager",
         | 
| 537 | 
            +
                "PathType",
         | 
| 538 | 
            +
                "DeploymentContext",
         | 
| 539 | 
            +
                "PathContext",
         | 
| 540 | 
            +
                "get_path_manager",
         | 
| 541 | 
            +
                "get_project_root",
         | 
| 542 | 
            +
                "get_framework_root",
         | 
| 543 | 
            +
                "get_package_root",
         | 
| 544 | 
            +
                "get_scripts_dir",
         | 
| 545 | 
            +
                "get_agents_dir",
         | 
| 546 | 
            +
                "get_config_dir",
         | 
| 547 | 
            +
                "find_file_upwards",
         | 
| 548 | 
            +
                "get_package_resource_path",
         | 
| 549 | 
            +
            ]
         | 
    
        claude_mpm/dashboard/index.html
    CHANGED
    
    
| @@ -5,30 +5,64 @@ import os | |
| 5 5 | 
             
            import webbrowser
         | 
| 6 6 | 
             
            from pathlib import Path
         | 
| 7 7 |  | 
| 8 | 
            +
            try:
         | 
| 9 | 
            +
                from ..services.port_manager import PortManager
         | 
| 10 | 
            +
            except ImportError:
         | 
| 11 | 
            +
                # Fallback for when running as standalone script
         | 
| 12 | 
            +
                import sys
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                sys.path.insert(0, str(Path(__file__).parent.parent.parent))
         | 
| 15 | 
            +
                from claude_mpm.services.port_manager import PortManager
         | 
| 16 | 
            +
             | 
| 17 | 
            +
             | 
| 18 | 
            +
            def discover_socketio_port():
         | 
| 19 | 
            +
                """Discover the port of the running SocketIO server, preferring 8765."""
         | 
| 20 | 
            +
                try:
         | 
| 21 | 
            +
                    port_manager = PortManager()
         | 
| 22 | 
            +
                    instances = port_manager.list_active_instances()
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    if instances:
         | 
| 25 | 
            +
                        # First, check if port 8765 is being used
         | 
| 26 | 
            +
                        for instance in instances:
         | 
| 27 | 
            +
                            if instance.get("port") == 8765:
         | 
| 28 | 
            +
                                return 8765
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                        # If 8765 is not available, return the first active instance port
         | 
| 31 | 
            +
                        return instances[0].get("port", 8765)
         | 
| 32 | 
            +
                    else:
         | 
| 33 | 
            +
                        print("⚠️  No active SocketIO instances found, using default port 8765")
         | 
| 34 | 
            +
                        return 8765
         | 
| 35 | 
            +
                except Exception as e:
         | 
| 36 | 
            +
                    print(f"⚠️  Failed to discover SocketIO port: {e}")
         | 
| 37 | 
            +
                    print("   Using default port 8765")
         | 
| 38 | 
            +
                    return 8765
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 8 41 | 
             
            def open_dashboard(port=8765, autoconnect=True):
         | 
| 9 42 | 
             
                """Open the dashboard HTML file directly in the browser.
         | 
| 10 | 
            -
             | 
| 43 | 
            +
             | 
| 11 44 | 
             
                Args:
         | 
| 12 | 
            -
                    port: Socket.IO server port to connect to
         | 
| 45 | 
            +
                    port: Socket.IO server port to connect to (defaults to 8765, auto-discovers if needed)
         | 
| 13 46 | 
             
                    autoconnect: Whether to auto-connect on load
         | 
| 14 47 | 
             
                """
         | 
| 15 | 
            -
                #  | 
| 16 | 
            -
                 | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
                 | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                print(f"🌐 Opening  | 
| 27 | 
            -
                print(f"📡 Dashboard  | 
| 48 | 
            +
                # If default port 8765 is specified, check if we need to auto-discover
         | 
| 49 | 
            +
                if port == 8765:
         | 
| 50 | 
            +
                    discovered_port = discover_socketio_port()
         | 
| 51 | 
            +
                    if discovered_port != 8765:
         | 
| 52 | 
            +
                        print(
         | 
| 53 | 
            +
                            f"🔍 SocketIO server found on port {discovered_port} instead of default 8765"
         | 
| 54 | 
            +
                        )
         | 
| 55 | 
            +
                        port = discovered_port
         | 
| 56 | 
            +
                # Build HTTP URL to connect to the SocketIO server's dashboard
         | 
| 57 | 
            +
                dashboard_url = f"http://localhost:{port}"
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                print(f"🌐 Opening dashboard: {dashboard_url}")
         | 
| 60 | 
            +
                print(f"📡 Dashboard served by Socket.IO server at localhost:{port}")
         | 
| 28 61 | 
             
                webbrowser.open(dashboard_url)
         | 
| 29 | 
            -
             | 
| 62 | 
            +
             | 
| 30 63 | 
             
                return dashboard_url
         | 
| 31 64 |  | 
| 65 | 
            +
             | 
| 32 66 | 
             
            if __name__ == "__main__":
         | 
| 33 67 | 
             
                # Test opening the dashboard
         | 
| 34 | 
            -
                open_dashboard()
         | 
| 68 | 
            +
                open_dashboard()
         | 
| @@ -0,0 +1,2 @@ | |
| 1 | 
            +
            class e{constructor(e){this.eventViewer=e,this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map},console.log("Agent inference system initialized")}initialize(){this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map}}inferAgentFromEvent(e){const t=e.data||{},n=e.session_id||t.session_id||"unknown",a=e.hook_event_name||t.hook_event_name||e.type||"",s=e.subtype||t.subtype||"",i=e.tool_name||t.tool_name||"";if(Math.random()<.1&&console.log("Agent inference debug:",{eventType:a,toolName:i,hasData:!!e.data,dataKeys:Object.keys(t),eventKeys:Object.keys(e),agentType:e.agent_type||t.agent_type,subagentType:e.subagent_type||t.subagent_type}),"SubagentStop"===a||"subagent_stop"===s){const i=this.extractAgentNameFromEvent(e);return console.log("SubagentStop event detected:",{agentName:i,sessionId:n,eventType:a,subtype:s,rawAgentType:e.agent_type||t.agent_type}),{type:"subagent",confidence:"definitive",agentName:i,reason:"SubagentStop event"}}if("Stop"===a||"stop"===s)return{type:"main_agent",confidence:"definitive",agentName:"PM",reason:"Stop event"};if("Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return console.log("Task delegation detected:",{agentName:t,sessionId:n,eventType:a}),{type:"subagent",confidence:"high",agentName:t,reason:"Task tool with subagent_type"}}if("PreToolUse"===a&&"Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return{type:"subagent",confidence:"high",agentName:t,reason:"PreToolUse Task delegation"}}{const e=n.toLowerCase();if(["subagent","task","agent-"].some(t=>e.includes(t)))return{type:"subagent",confidence:"medium",agentName:"Subagent",reason:"Session ID pattern"}}const o=e.agent_type||t.agent_type||e.agent_id||t.agent_id,g=e.subagent_type||t.subagent_type;if(g&&"unknown"!==g)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(g),reason:"subagent_type field"};if(o&&"unknown"!==o&&"main"!==o)return{type:"subagent",confidence:"medium",agentName:this.normalizeAgentName(o),reason:"agent_type field"};if(t.delegation_details?.agent_type)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(t.delegation_details.agent_type),reason:"delegation_details"};if(e.type&&e.type.startsWith("hook.")){const a=e.type.replace("hook.","");if("subagent_start"===a||"SubagentStart"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return console.log("SubagentStart event from Socket.IO:",{agentName:e,sessionId:n,hookType:a}),{type:"subagent",confidence:"definitive",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStart"}}if("subagent_stop"===a||"SubagentStop"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStop"}}}return{type:"main_agent",confidence:"default",agentName:"PM",reason:"default classification"}}normalizeAgentName(e){if(!e)return"Unknown";const t={engineer:"Engineer Agent",research:"Research Agent",qa:"QA Agent",documentation:"Documentation Agent",security:"Security Agent",ops:"Ops Agent",version_control:"Version Control Agent",data_engineer:"Data Engineer Agent",test_integration:"Test Integration Agent",pm:"PM Agent"}[e.toLowerCase()];if(t)return t;let n=e.replace(/_/g," ").split(" ").map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(" ");return n.toLowerCase().includes("agent")||(n+=" Agent"),n}extractSubagentTypeFromTask(e){let t=null;return e.tool_parameters?.subagent_type?t=e.tool_parameters.subagent_type:e.data?.tool_parameters?.subagent_type?t=e.data.tool_parameters.subagent_type:e.data?.delegation_details?.agent_type?t=e.data.delegation_details.agent_type:e.tool_input?.subagent_type&&(t=e.tool_input.subagent_type),t?this.normalizeAgentName(t):null}extractAgentNameFromEvent(e){const t=e.data||{};if("Task"===e.tool_name||"Task"===t.tool_name){const t=this.extractSubagentTypeFromTask(e);if(t)return t}return e.subagent_type&&"unknown"!==e.subagent_type?this.normalizeAgentName(e.subagent_type):t.subagent_type&&"unknown"!==t.subagent_type?this.normalizeAgentName(t.subagent_type):t.delegation_details?.agent_type&&"unknown"!==t.delegation_details.agent_type?this.normalizeAgentName(t.delegation_details.agent_type):e.agent_type&&!["main","unknown"].includes(e.agent_type)?this.normalizeAgentName(e.agent_type):t.agent_type&&!["main","unknown"].includes(t.agent_type)?this.normalizeAgentName(t.agent_type):e.agent_id&&!["main","unknown"].includes(e.agent_id)?this.normalizeAgentName(e.agent_id):t.agent_id&&!["main","unknown"].includes(t.agent_id)?this.normalizeAgentName(t.agent_id):e.agent&&"unknown"!==e.agent?this.normalizeAgentName(e.agent):e.name&&"unknown"!==e.name?this.normalizeAgentName(e.name):"Unknown"}processAgentInference(){const e=this.eventViewer.events;this.state.currentDelegation=null,this.state.sessionAgents.clear(),this.state.eventAgentMap.clear(),this.state.pmDelegations.clear(),this.state.agentToDelegation.clear(),console.log("Processing agent inference for",e.length,"events"),e&&0!==e.length?(e.forEach((e,t)=>{let n;try{const a=this.inferAgentFromEvent(e),s=e.session_id||e.data?.session_id||"default";if(n=a,this.state.currentDelegation&&"default"===a.confidence&&s===this.state.currentDelegation.sessionId&&(n={type:"subagent",confidence:"inherited",agentName:this.state.currentDelegation.agentName,reason:"inherited from delegation context"}),"Task"===e.tool_name&&"subagent"===a.type){const n=`pm_${s}_${t}_${a.agentName}`,i={id:n,agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,pmCall:e,timestamp:e.timestamp,agentEvents:[]};this.state.pmDelegations.set(n,i),this.state.agentToDelegation.set(a.agentName,n),this.state.currentDelegation={agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,delegationId:n},console.log("Delegation started:",this.state.currentDelegation)}else if("definitive"===a.confidence&&"SubagentStop event"===a.reason&&this.state.currentDelegation){this.state.currentDelegation.endIndex=t;const e=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);e&&(e.endIndex=t),console.log("Delegation ended:",this.state.currentDelegation),this.state.currentDelegation=null}if(this.state.currentDelegation&&"subagent"===n.type){const a=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);a&&a.agentEvents.push({eventIndex:t,event:e,inference:n})}this.state.eventAgentMap.set(t,n),this.state.sessionAgents.set(s,n),t<5&&console.log(`Event ${t} agent inference:`,{event_type:e.type||e.hook_event_name,subtype:e.subtype,tool_name:e.tool_name,inference:n,hasData:!!e.data,agentType:e.agent_type||e.data?.agent_type})}catch(a){console.error(`Error processing event ${t} for agent inference:`,a),n||(n={type:"main_agent",confidence:"error",agentName:"PM",reason:"error during processing"}),this.state.eventAgentMap.set(t,n)}}),console.log("Agent inference processing complete. Results:",{total_events:e.length,inferred_agents:this.state.eventAgentMap.size,unique_sessions:this.state.sessionAgents.size,pm_delegations:this.state.pmDelegations.size,agent_to_delegation_mappings:this.state.agentToDelegation.size})):console.log("No events to process for agent inference")}getInferredAgent(e){return this.state.eventAgentMap.get(e)||null}getInferredAgentForEvent(e){const t=this.eventViewer.events;let n=t.indexOf(e);if(-1===n&&e.timestamp&&(n=t.findIndex(t=>t.timestamp===e.timestamp&&t.session_id===e.session_id)),-1===n)return console.log("Agent inference: Could not find event in events array, performing inline inference"),this.inferAgentFromEvent(e);let a=this.getInferredAgent(n);return a||(a=this.inferAgentFromEvent(e),this.state.eventAgentMap.set(n,a)),a}getCurrentDelegation(){return this.state.currentDelegation}getSessionAgents(){return this.state.sessionAgents}getEventAgentMap(){return this.state.eventAgentMap}getPMDelegations(){return this.state.pmDelegations}getAgentToDelegationMap(){return this.state.agentToDelegation}getUniqueAgentInstances(){const e=new Map;for(const[a,s]of this.state.pmDelegations){const t=s.agentName;e.has(t)||e.set(t,{id:`consolidated_${t}`,type:"consolidated_agent",agentName:t,delegations:[],pmCalls:[],allEvents:[],firstTimestamp:s.timestamp,lastTimestamp:s.timestamp,totalEventCount:s.agentEvents.length,delegationCount:1});const n=e.get(t);n.delegations.push({id:a,pmCall:s.pmCall,timestamp:s.timestamp,eventCount:s.agentEvents.length,startIndex:s.startIndex,endIndex:s.endIndex,events:s.agentEvents}),s.pmCall&&n.pmCalls.push(s.pmCall),n.allEvents=n.allEvents.concat(s.agentEvents),new Date(s.timestamp)<new Date(n.firstTimestamp)&&(n.firstTimestamp=s.timestamp),new Date(s.timestamp)>new Date(n.lastTimestamp)&&(n.lastTimestamp=s.timestamp),n.totalEventCount+=s.agentEvents.length,n.delegationCount++}const t=this.eventViewer.events;for(let a=0;a<t.length;a++){const n=this.getInferredAgent(a);n&&"subagent"===n.type&&!e.has(n.agentName)&&e.set(n.agentName,{id:`consolidated_${n.agentName}`,type:"consolidated_agent",agentName:n.agentName,delegations:[{id:`implied_pm_${n.agentName}_${a}`,pmCall:null,timestamp:t[a].timestamp,eventCount:1,startIndex:a,endIndex:null,events:[{eventIndex:a,event:t[a],inference:n}]}],pmCalls:[],allEvents:[{eventIndex:a,event:t[a],inference:n}],firstTimestamp:t[a].timestamp,lastTimestamp:t[a].timestamp,totalEventCount:1,delegationCount:1,isImplied:!0})}const n=Array.from(e.values()).sort((e,t)=>new Date(e.firstTimestamp)-new Date(t.firstTimestamp));return console.log("Consolidated unique agents:",{total_unique_agents:n.length,agents:n.map(e=>({name:e.agentName,delegations:e.delegationCount,totalEvents:e.totalEventCount}))}),n}}export{e as A};
         | 
| 2 | 
            +
            //# sourceMappingURL=agent-inference.js.map
         |