claude-mpm 3.9.9__py3-none-any.whl → 4.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +155 -0
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +1 -1
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +90 -49
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +21 -18
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +143 -762
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +203 -81
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +305 -197
- claude_mpm/cli/parser.py +24 -1150
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +104 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +217 -0
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +36 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +120 -54
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +571 -0
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +40 -23
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
- claude_mpm/services/mcp_gateway/main.py +307 -127
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
- claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +223 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +145 -65
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +170 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +20 -534
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +9 -0
- claude_mpm/storage/state_storage.py +552 -0
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/memory_guardian.py +0 -770
- claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.9.dist-info/RECORD +0 -293
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            from pathlib import Path
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            """CLI commands for the Event Aggregator service.
         | 
| 2 4 |  | 
| 3 5 | 
             
            WHY: Provides command-line interface for managing the event aggregator service
         | 
| @@ -6,41 +8,38 @@ that captures Socket.IO events and saves them as structured session documents. | |
| 6 8 |  | 
| 7 9 | 
             
            import json
         | 
| 8 10 | 
             
            import sys
         | 
| 9 | 
            -
            from pathlib import Path
         | 
| 10 | 
            -
            from typing import Optional
         | 
| 11 11 |  | 
| 12 | 
            +
            from ...core.logger import get_logger
         | 
| 13 | 
            +
            from ...models.agent_session import AgentSession
         | 
| 12 14 | 
             
            from ...services.event_aggregator import (
         | 
| 15 | 
            +
                aggregator_status,
         | 
| 13 16 | 
             
                get_aggregator,
         | 
| 14 17 | 
             
                start_aggregator,
         | 
| 15 18 | 
             
                stop_aggregator,
         | 
| 16 | 
            -
                aggregator_status
         | 
| 17 19 | 
             
            )
         | 
| 18 | 
            -
            from ...models.agent_session import AgentSession
         | 
| 19 | 
            -
            from ...core.logger import get_logger
         | 
| 20 | 
            -
             | 
| 21 20 |  | 
| 22 21 | 
             
            logger = get_logger("cli.aggregate")
         | 
| 23 22 |  | 
| 24 23 |  | 
| 25 24 | 
             
            def aggregate_command(args):
         | 
| 26 25 | 
             
                """Main entry point for aggregate commands.
         | 
| 27 | 
            -
             | 
| 26 | 
            +
             | 
| 28 27 | 
             
                WHY: Routes subcommands to appropriate handlers for managing the
         | 
| 29 28 | 
             
                event aggregator service.
         | 
| 30 29 | 
             
                """
         | 
| 31 30 | 
             
                subcommand = args.aggregate_subcommand
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                if subcommand ==  | 
| 31 | 
            +
             | 
| 32 | 
            +
                if subcommand == "start":
         | 
| 34 33 | 
             
                    return start_command(args)
         | 
| 35 | 
            -
                elif subcommand ==  | 
| 34 | 
            +
                elif subcommand == "stop":
         | 
| 36 35 | 
             
                    return stop_command(args)
         | 
| 37 | 
            -
                elif subcommand ==  | 
| 36 | 
            +
                elif subcommand == "status":
         | 
| 38 37 | 
             
                    return status_command(args)
         | 
| 39 | 
            -
                elif subcommand ==  | 
| 38 | 
            +
                elif subcommand == "sessions":
         | 
| 40 39 | 
             
                    return sessions_command(args)
         | 
| 41 | 
            -
                elif subcommand ==  | 
| 40 | 
            +
                elif subcommand == "view":
         | 
| 42 41 | 
             
                    return view_command(args)
         | 
| 43 | 
            -
                elif subcommand ==  | 
| 42 | 
            +
                elif subcommand == "export":
         | 
| 44 43 | 
             
                    return export_command(args)
         | 
| 45 44 | 
             
                else:
         | 
| 46 45 | 
             
                    print(f"Unknown subcommand: {subcommand}", file=sys.stderr)
         | 
| @@ -49,18 +48,19 @@ def aggregate_command(args): | |
| 49 48 |  | 
| 50 49 | 
             
            def start_command(args):
         | 
| 51 50 | 
             
                """Start the event aggregator service.
         | 
| 52 | 
            -
             | 
| 51 | 
            +
             | 
| 53 52 | 
             
                WHY: Starts capturing events from the Socket.IO dashboard server
         | 
| 54 53 | 
             
                for building complete session documents.
         | 
| 55 54 | 
             
                """
         | 
| 56 55 | 
             
                print("Starting Event Aggregator service...")
         | 
| 57 | 
            -
             | 
| 56 | 
            +
             | 
| 58 57 | 
             
                # Check if Socket.IO server is running
         | 
| 59 58 | 
             
                import socket
         | 
| 59 | 
            +
             | 
| 60 60 | 
             
                try:
         | 
| 61 61 | 
             
                    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
         | 
| 62 62 | 
             
                        s.settimeout(1)
         | 
| 63 | 
            -
                        result = s.connect_ex(( | 
| 63 | 
            +
                        result = s.connect_ex(("127.0.0.1", 8765))
         | 
| 64 64 | 
             
                        if result != 0:
         | 
| 65 65 | 
             
                            print("Warning: Socket.IO server not detected on port 8765")
         | 
| 66 66 | 
             
                            print("The aggregator requires the dashboard server to be running.")
         | 
| @@ -69,32 +69,35 @@ def start_command(args): | |
| 69 69 | 
             
                                return 1
         | 
| 70 70 | 
             
                except Exception as e:
         | 
| 71 71 | 
             
                    logger.error(f"Error checking server status: {e}")
         | 
| 72 | 
            -
             | 
| 72 | 
            +
             | 
| 73 73 | 
             
                # Start the aggregator
         | 
| 74 74 | 
             
                if start_aggregator():
         | 
| 75 75 | 
             
                    print("✅ Event Aggregator started successfully")
         | 
| 76 76 | 
             
                    print(f"Capturing events from localhost:8765")
         | 
| 77 77 | 
             
                    print(f"Sessions will be saved to: .claude-mpm/sessions/")
         | 
| 78 | 
            -
             | 
| 78 | 
            +
             | 
| 79 79 | 
             
                    # Show initial status
         | 
| 80 80 | 
             
                    status = aggregator_status()
         | 
| 81 81 | 
             
                    print(f"\nStatus:")
         | 
| 82 82 | 
             
                    print(f"  Connected: {status['connected']}")
         | 
| 83 83 | 
             
                    print(f"  Active sessions: {status['active_sessions']}")
         | 
| 84 | 
            -
             | 
| 84 | 
            +
             | 
| 85 85 | 
             
                    if args.daemon:
         | 
| 86 | 
            -
                        print( | 
| 86 | 
            +
                        print(
         | 
| 87 | 
            +
                            "\nAggregator running in background. Use 'claude-mpm aggregate stop' to stop it."
         | 
| 88 | 
            +
                        )
         | 
| 87 89 | 
             
                    else:
         | 
| 88 90 | 
             
                        print("\nPress Ctrl+C to stop the aggregator...")
         | 
| 89 91 | 
             
                        try:
         | 
| 90 92 | 
             
                            # Keep running until interrupted
         | 
| 91 93 | 
             
                            import time
         | 
| 94 | 
            +
             | 
| 92 95 | 
             
                            while True:
         | 
| 93 96 | 
             
                                time.sleep(1)
         | 
| 94 97 | 
             
                        except KeyboardInterrupt:
         | 
| 95 98 | 
             
                            print("\nStopping aggregator...")
         | 
| 96 99 | 
             
                            stop_aggregator()
         | 
| 97 | 
            -
             | 
| 100 | 
            +
             | 
| 98 101 | 
             
                    return 0
         | 
| 99 102 | 
             
                else:
         | 
| 100 103 | 
             
                    print("❌ Failed to start Event Aggregator")
         | 
| @@ -104,42 +107,43 @@ def start_command(args): | |
| 104 107 |  | 
| 105 108 | 
             
            def stop_command(args):
         | 
| 106 109 | 
             
                """Stop the event aggregator service.
         | 
| 107 | 
            -
             | 
| 110 | 
            +
             | 
| 108 111 | 
             
                WHY: Gracefully stops the aggregator and saves any active sessions.
         | 
| 109 112 | 
             
                """
         | 
| 110 113 | 
             
                print("Stopping Event Aggregator service...")
         | 
| 111 | 
            -
             | 
| 114 | 
            +
             | 
| 112 115 | 
             
                # Get status before stopping
         | 
| 113 116 | 
             
                status = aggregator_status()
         | 
| 114 | 
            -
                active_sessions = status.get( | 
| 115 | 
            -
             | 
| 117 | 
            +
                active_sessions = status.get("active_sessions", 0)
         | 
| 118 | 
            +
             | 
| 116 119 | 
             
                if active_sessions > 0:
         | 
| 117 120 | 
             
                    print(f"Saving {active_sessions} active session(s)...")
         | 
| 118 | 
            -
             | 
| 121 | 
            +
             | 
| 119 122 | 
             
                stop_aggregator()
         | 
| 120 123 | 
             
                print("✅ Event Aggregator stopped")
         | 
| 121 | 
            -
             | 
| 124 | 
            +
             | 
| 122 125 | 
             
                # Show final statistics
         | 
| 123 | 
            -
                if status[ | 
| 126 | 
            +
                if status["total_events"] > 0:
         | 
| 124 127 | 
             
                    print(f"\nStatistics:")
         | 
| 125 128 | 
             
                    print(f"  Total events captured: {status['total_events']}")
         | 
| 126 129 | 
             
                    print(f"  Sessions completed: {status['sessions_completed']}")
         | 
| 127 130 | 
             
                    print(f"  Events by type:")
         | 
| 128 | 
            -
                    for event_type, count in sorted( | 
| 129 | 
            -
             | 
| 131 | 
            +
                    for event_type, count in sorted(
         | 
| 132 | 
            +
                        status["events_by_type"].items(), key=lambda x: x[1], reverse=True
         | 
| 133 | 
            +
                    )[:5]:
         | 
| 130 134 | 
             
                        print(f"    {event_type}: {count}")
         | 
| 131 | 
            -
             | 
| 135 | 
            +
             | 
| 132 136 | 
             
                return 0
         | 
| 133 137 |  | 
| 134 138 |  | 
| 135 139 | 
             
            def status_command(args):
         | 
| 136 140 | 
             
                """Show status of the event aggregator service.
         | 
| 137 | 
            -
             | 
| 141 | 
            +
             | 
| 138 142 | 
             
                WHY: Provides visibility into what the aggregator is doing and
         | 
| 139 143 | 
             
                what it has captured.
         | 
| 140 144 | 
             
                """
         | 
| 141 145 | 
             
                status = aggregator_status()
         | 
| 142 | 
            -
             | 
| 146 | 
            +
             | 
| 143 147 | 
             
                print("Event Aggregator Status")
         | 
| 144 148 | 
             
                print("=" * 50)
         | 
| 145 149 | 
             
                print(f"Running: {status['running']}")
         | 
| @@ -148,37 +152,38 @@ def status_command(args): | |
| 148 152 | 
             
                print(f"Save directory: {status['save_directory']}")
         | 
| 149 153 | 
             
                print()
         | 
| 150 154 | 
             
                print(f"Active sessions: {status['active_sessions']}")
         | 
| 151 | 
            -
                if status[ | 
| 152 | 
            -
                    for sid in status[ | 
| 155 | 
            +
                if status["active_session_ids"]:
         | 
| 156 | 
            +
                    for sid in status["active_session_ids"]:
         | 
| 153 157 | 
             
                        print(f"  - {sid}")
         | 
| 154 158 | 
             
                print()
         | 
| 155 159 | 
             
                print(f"Sessions completed: {status['sessions_completed']}")
         | 
| 156 160 | 
             
                print(f"Total events captured: {status['total_events']}")
         | 
| 157 | 
            -
             | 
| 158 | 
            -
                if status[ | 
| 161 | 
            +
             | 
| 162 | 
            +
                if status["events_by_type"]:
         | 
| 159 163 | 
             
                    print("\nTop event types:")
         | 
| 160 | 
            -
                    for event_type, count in sorted( | 
| 161 | 
            -
             | 
| 164 | 
            +
                    for event_type, count in sorted(
         | 
| 165 | 
            +
                        status["events_by_type"].items(), key=lambda x: x[1], reverse=True
         | 
| 166 | 
            +
                    )[:10]:
         | 
| 162 167 | 
             
                        print(f"  {event_type:30s} {count:6d}")
         | 
| 163 | 
            -
             | 
| 168 | 
            +
             | 
| 164 169 | 
             
                return 0
         | 
| 165 170 |  | 
| 166 171 |  | 
| 167 172 | 
             
            def sessions_command(args):
         | 
| 168 173 | 
             
                """List captured sessions.
         | 
| 169 | 
            -
             | 
| 174 | 
            +
             | 
| 170 175 | 
             
                WHY: Shows what sessions have been captured for analysis.
         | 
| 171 176 | 
             
                """
         | 
| 172 177 | 
             
                aggregator = get_aggregator()
         | 
| 173 178 | 
             
                sessions = aggregator.list_sessions(limit=args.limit)
         | 
| 174 | 
            -
             | 
| 179 | 
            +
             | 
| 175 180 | 
             
                if not sessions:
         | 
| 176 181 | 
             
                    print("No sessions found")
         | 
| 177 182 | 
             
                    return 0
         | 
| 178 | 
            -
             | 
| 183 | 
            +
             | 
| 179 184 | 
             
                print(f"Recent Sessions (showing {len(sessions)} of {args.limit} max)")
         | 
| 180 185 | 
             
                print("=" * 80)
         | 
| 181 | 
            -
             | 
| 186 | 
            +
             | 
| 182 187 | 
             
                for session in sessions:
         | 
| 183 188 | 
             
                    print(f"\n📁 {session['file']}")
         | 
| 184 189 | 
             
                    print(f"   Session ID: {session['session_id']}")
         | 
| @@ -187,37 +192,37 @@ def sessions_command(args): | |
| 187 192 | 
             
                    print(f"   Events: {session['events']}")
         | 
| 188 193 | 
             
                    print(f"   Delegations: {session['delegations']}")
         | 
| 189 194 | 
             
                    print(f"   Prompt: {session['initial_prompt']}")
         | 
| 190 | 
            -
             | 
| 195 | 
            +
             | 
| 191 196 | 
             
                print(f"\nUse 'claude-mpm aggregate view <session_id>' to view details")
         | 
| 192 | 
            -
             | 
| 197 | 
            +
             | 
| 193 198 | 
             
                return 0
         | 
| 194 199 |  | 
| 195 200 |  | 
| 196 201 | 
             
            def view_command(args):
         | 
| 197 202 | 
             
                """View details of a specific session.
         | 
| 198 | 
            -
             | 
| 203 | 
            +
             | 
| 199 204 | 
             
                WHY: Allows detailed inspection of what happened during a session.
         | 
| 200 205 | 
             
                """
         | 
| 201 206 | 
             
                aggregator = get_aggregator()
         | 
| 202 | 
            -
             | 
| 207 | 
            +
             | 
| 203 208 | 
             
                # Load the session
         | 
| 204 209 | 
             
                session = aggregator.load_session(args.session_id)
         | 
| 205 | 
            -
             | 
| 210 | 
            +
             | 
| 206 211 | 
             
                if not session:
         | 
| 207 212 | 
             
                    print(f"Session not found: {args.session_id}")
         | 
| 208 213 | 
             
                    print("Use 'claude-mpm aggregate sessions' to list available sessions")
         | 
| 209 214 | 
             
                    return 1
         | 
| 210 | 
            -
             | 
| 215 | 
            +
             | 
| 211 216 | 
             
                print(f"Session: {session.session_id}")
         | 
| 212 217 | 
             
                print("=" * 80)
         | 
| 213 218 | 
             
                print(f"Start: {session.start_time}")
         | 
| 214 219 | 
             
                print(f"End: {session.end_time or 'In progress'}")
         | 
| 215 220 | 
             
                print(f"Working directory: {session.working_directory}")
         | 
| 216 221 | 
             
                print(f"Launch method: {session.launch_method}")
         | 
| 217 | 
            -
             | 
| 222 | 
            +
             | 
| 218 223 | 
             
                if session.git_branch:
         | 
| 219 224 | 
             
                    print(f"Git branch: {session.git_branch}")
         | 
| 220 | 
            -
             | 
| 225 | 
            +
             | 
| 221 226 | 
             
                print(f"\nInitial prompt:")
         | 
| 222 227 | 
             
                print("-" * 40)
         | 
| 223 228 | 
             
                if session.initial_prompt:
         | 
| @@ -226,7 +231,7 @@ def view_command(args): | |
| 226 231 | 
             
                        print("...")
         | 
| 227 232 | 
             
                else:
         | 
| 228 233 | 
             
                    print("(No prompt captured)")
         | 
| 229 | 
            -
             | 
| 234 | 
            +
             | 
| 230 235 | 
             
                print(f"\nMetrics:")
         | 
| 231 236 | 
             
                print("-" * 40)
         | 
| 232 237 | 
             
                metrics = session.metrics
         | 
| @@ -234,24 +239,24 @@ def view_command(args): | |
| 234 239 | 
             
                print(f"Delegations: {metrics.total_delegations}")
         | 
| 235 240 | 
             
                print(f"Tool calls: {metrics.total_tool_calls}")
         | 
| 236 241 | 
             
                print(f"File operations: {metrics.total_file_operations}")
         | 
| 237 | 
            -
             | 
| 242 | 
            +
             | 
| 238 243 | 
             
                if metrics.session_duration_ms:
         | 
| 239 244 | 
             
                    duration_sec = metrics.session_duration_ms / 1000
         | 
| 240 245 | 
             
                    print(f"Duration: {duration_sec:.1f} seconds")
         | 
| 241 | 
            -
             | 
| 246 | 
            +
             | 
| 242 247 | 
             
                if metrics.agents_used:
         | 
| 243 248 | 
             
                    print(f"\nAgents used: {', '.join(sorted(metrics.agents_used))}")
         | 
| 244 | 
            -
             | 
| 249 | 
            +
             | 
| 245 250 | 
             
                if metrics.tools_used:
         | 
| 246 251 | 
             
                    print(f"\nTools used: {', '.join(sorted(metrics.tools_used))}")
         | 
| 247 | 
            -
             | 
| 252 | 
            +
             | 
| 248 253 | 
             
                if metrics.files_modified:
         | 
| 249 254 | 
             
                    print(f"\nFiles modified ({len(metrics.files_modified)}):")
         | 
| 250 255 | 
             
                    for filepath in sorted(metrics.files_modified)[:10]:
         | 
| 251 256 | 
             
                        print(f"  - {filepath}")
         | 
| 252 257 | 
             
                    if len(metrics.files_modified) > 10:
         | 
| 253 258 | 
             
                        print(f"  ... and {len(metrics.files_modified) - 10} more")
         | 
| 254 | 
            -
             | 
| 259 | 
            +
             | 
| 255 260 | 
             
                if session.delegations:
         | 
| 256 261 | 
             
                    print(f"\nDelegations ({len(session.delegations)}):")
         | 
| 257 262 | 
             
                    print("-" * 40)
         | 
| @@ -267,196 +272,172 @@ def view_command(args): | |
| 267 272 | 
             
                        print(f"   Status: {'✅ Success' if delegation.success else '❌ Failed'}")
         | 
| 268 273 | 
             
                        if delegation.error:
         | 
| 269 274 | 
             
                            print(f"   Error: {delegation.error}")
         | 
| 270 | 
            -
             | 
| 275 | 
            +
             | 
| 271 276 | 
             
                if args.show_events:
         | 
| 272 277 | 
             
                    print(f"\nEvents ({len(session.events)}):")
         | 
| 273 278 | 
             
                    print("-" * 40)
         | 
| 274 | 
            -
                    for event in session.events[:args.event_limit]:
         | 
| 279 | 
            +
                    for event in session.events[: args.event_limit]:
         | 
| 275 280 | 
             
                        print(f"{event.timestamp} [{event.category.value:10s}] {event.event_type}")
         | 
| 276 281 | 
             
                        if args.verbose:
         | 
| 277 282 | 
             
                            print(f"  Agent: {event.agent_context or 'N/A'}")
         | 
| 278 283 | 
             
                            if event.correlation_id:
         | 
| 279 284 | 
             
                                print(f"  Correlation: {event.correlation_id}")
         | 
| 280 | 
            -
             | 
| 285 | 
            +
             | 
| 281 286 | 
             
                if session.final_response and not args.no_response:
         | 
| 282 287 | 
             
                    print(f"\nFinal response:")
         | 
| 283 288 | 
             
                    print("-" * 40)
         | 
| 284 289 | 
             
                    print(session.final_response[:1000])
         | 
| 285 290 | 
             
                    if len(session.final_response) > 1000:
         | 
| 286 291 | 
             
                        print("...")
         | 
| 287 | 
            -
             | 
| 292 | 
            +
             | 
| 288 293 | 
             
                return 0
         | 
| 289 294 |  | 
| 290 295 |  | 
| 291 296 | 
             
            def export_command(args):
         | 
| 292 297 | 
             
                """Export a session to a file.
         | 
| 293 | 
            -
             | 
| 298 | 
            +
             | 
| 294 299 | 
             
                WHY: Allows sessions to be exported for external analysis or sharing.
         | 
| 295 300 | 
             
                """
         | 
| 296 301 | 
             
                aggregator = get_aggregator()
         | 
| 297 | 
            -
             | 
| 302 | 
            +
             | 
| 298 303 | 
             
                # Load the session
         | 
| 299 304 | 
             
                session = aggregator.load_session(args.session_id)
         | 
| 300 | 
            -
             | 
| 305 | 
            +
             | 
| 301 306 | 
             
                if not session:
         | 
| 302 307 | 
             
                    print(f"Session not found: {args.session_id}")
         | 
| 303 308 | 
             
                    return 1
         | 
| 304 | 
            -
             | 
| 309 | 
            +
             | 
| 305 310 | 
             
                # Determine output file
         | 
| 306 311 | 
             
                if args.output:
         | 
| 307 312 | 
             
                    output_path = Path(args.output)
         | 
| 308 313 | 
             
                else:
         | 
| 309 314 | 
             
                    output_path = Path(f"session_{session.session_id[:8]}_export.json")
         | 
| 310 | 
            -
             | 
| 315 | 
            +
             | 
| 311 316 | 
             
                # Export based on format
         | 
| 312 | 
            -
                if args.format ==  | 
| 317 | 
            +
                if args.format == "json":
         | 
| 313 318 | 
             
                    # Full JSON export
         | 
| 314 | 
            -
                    with open(output_path,  | 
| 319 | 
            +
                    with open(output_path, "w") as f:
         | 
| 315 320 | 
             
                        json.dump(session.to_dict(), f, indent=2)
         | 
| 316 321 | 
             
                    print(f"✅ Exported session to {output_path}")
         | 
| 317 | 
            -
             | 
| 318 | 
            -
                elif args.format ==  | 
| 322 | 
            +
             | 
| 323 | 
            +
                elif args.format == "summary":
         | 
| 319 324 | 
             
                    # Summary export
         | 
| 320 325 | 
             
                    summary = {
         | 
| 321 | 
            -
                         | 
| 322 | 
            -
                         | 
| 323 | 
            -
                         | 
| 324 | 
            -
                         | 
| 325 | 
            -
                         | 
| 326 | 
            -
                         | 
| 327 | 
            -
                         | 
| 328 | 
            -
                         | 
| 326 | 
            +
                        "session_id": session.session_id,
         | 
| 327 | 
            +
                        "start_time": session.start_time,
         | 
| 328 | 
            +
                        "end_time": session.end_time,
         | 
| 329 | 
            +
                        "working_directory": session.working_directory,
         | 
| 330 | 
            +
                        "initial_prompt": session.initial_prompt,
         | 
| 331 | 
            +
                        "final_response": session.final_response,
         | 
| 332 | 
            +
                        "metrics": session.metrics.to_dict(),
         | 
| 333 | 
            +
                        "delegations_summary": [
         | 
| 329 334 | 
             
                            {
         | 
| 330 | 
            -
                                 | 
| 331 | 
            -
                                 | 
| 332 | 
            -
                                 | 
| 333 | 
            -
                                 | 
| 334 | 
            -
                                 | 
| 335 | 
            -
                                 | 
| 335 | 
            +
                                "agent": d.agent_type,
         | 
| 336 | 
            +
                                "task": d.task_description,
         | 
| 337 | 
            +
                                "duration_ms": d.duration_ms,
         | 
| 338 | 
            +
                                "success": d.success,
         | 
| 339 | 
            +
                                "tools_used": len(d.tool_operations),
         | 
| 340 | 
            +
                                "files_changed": len(d.file_changes),
         | 
| 336 341 | 
             
                            }
         | 
| 337 342 | 
             
                            for d in session.delegations
         | 
| 338 | 
            -
                        ]
         | 
| 343 | 
            +
                        ],
         | 
| 339 344 | 
             
                    }
         | 
| 340 | 
            -
             | 
| 341 | 
            -
                    with open(output_path,  | 
| 345 | 
            +
             | 
| 346 | 
            +
                    with open(output_path, "w") as f:
         | 
| 342 347 | 
             
                        json.dump(summary, f, indent=2)
         | 
| 343 348 | 
             
                    print(f"✅ Exported session summary to {output_path}")
         | 
| 344 | 
            -
             | 
| 345 | 
            -
                elif args.format ==  | 
| 349 | 
            +
             | 
| 350 | 
            +
                elif args.format == "events":
         | 
| 346 351 | 
             
                    # Events-only export
         | 
| 347 352 | 
             
                    events_data = [e.to_dict() for e in session.events]
         | 
| 348 | 
            -
             | 
| 349 | 
            -
                    with open(output_path,  | 
| 353 | 
            +
             | 
| 354 | 
            +
                    with open(output_path, "w") as f:
         | 
| 350 355 | 
             
                        json.dump(events_data, f, indent=2)
         | 
| 351 356 | 
             
                    print(f"✅ Exported {len(events_data)} events to {output_path}")
         | 
| 352 | 
            -
             | 
| 357 | 
            +
             | 
| 353 358 | 
             
                return 0
         | 
| 354 359 |  | 
| 355 360 |  | 
| 356 361 | 
             
            def add_aggregate_parser(subparsers):
         | 
| 357 362 | 
             
                """Add the aggregate command parser.
         | 
| 358 | 
            -
             | 
| 363 | 
            +
             | 
| 359 364 | 
             
                WHY: Integrates the aggregator commands into the main CLI system.
         | 
| 360 365 | 
             
                """
         | 
| 361 366 | 
             
                aggregate_parser = subparsers.add_parser(
         | 
| 362 | 
            -
                     | 
| 363 | 
            -
                    help='Manage event aggregator for capturing agent sessions'
         | 
| 367 | 
            +
                    "aggregate", help="Manage event aggregator for capturing agent sessions"
         | 
| 364 368 | 
             
                )
         | 
| 365 | 
            -
             | 
| 369 | 
            +
             | 
| 366 370 | 
             
                aggregate_subparsers = aggregate_parser.add_subparsers(
         | 
| 367 | 
            -
                    dest= | 
| 368 | 
            -
                    help='Aggregator subcommands'
         | 
| 371 | 
            +
                    dest="aggregate_subcommand", help="Aggregator subcommands"
         | 
| 369 372 | 
             
                )
         | 
| 370 | 
            -
             | 
| 373 | 
            +
             | 
| 371 374 | 
             
                # Start command
         | 
| 372 375 | 
             
                start_parser = aggregate_subparsers.add_parser(
         | 
| 373 | 
            -
                     | 
| 374 | 
            -
                    help='Start the event aggregator service'
         | 
| 376 | 
            +
                    "start", help="Start the event aggregator service"
         | 
| 375 377 | 
             
                )
         | 
| 376 378 | 
             
                start_parser.add_argument(
         | 
| 377 | 
            -
                     | 
| 378 | 
            -
                    action='store_true',
         | 
| 379 | 
            -
                    help='Run in background as daemon'
         | 
| 379 | 
            +
                    "--daemon", "-d", action="store_true", help="Run in background as daemon"
         | 
| 380 380 | 
             
                )
         | 
| 381 381 | 
             
                start_parser.add_argument(
         | 
| 382 | 
            -
                     | 
| 383 | 
            -
                     | 
| 384 | 
            -
                     | 
| 382 | 
            +
                    "--force",
         | 
| 383 | 
            +
                    "-f",
         | 
| 384 | 
            +
                    action="store_true",
         | 
| 385 | 
            +
                    help="Start even if Socket.IO server not detected",
         | 
| 385 386 | 
             
                )
         | 
| 386 | 
            -
             | 
| 387 | 
            +
             | 
| 387 388 | 
             
                # Stop command
         | 
| 388 | 
            -
                aggregate_subparsers.add_parser(
         | 
| 389 | 
            -
             | 
| 390 | 
            -
                    help='Stop the event aggregator service'
         | 
| 391 | 
            -
                )
         | 
| 392 | 
            -
                
         | 
| 389 | 
            +
                aggregate_subparsers.add_parser("stop", help="Stop the event aggregator service")
         | 
| 390 | 
            +
             | 
| 393 391 | 
             
                # Status command
         | 
| 394 392 | 
             
                aggregate_subparsers.add_parser(
         | 
| 395 | 
            -
                     | 
| 396 | 
            -
                    help='Show aggregator status and statistics'
         | 
| 393 | 
            +
                    "status", help="Show aggregator status and statistics"
         | 
| 397 394 | 
             
                )
         | 
| 398 | 
            -
             | 
| 395 | 
            +
             | 
| 399 396 | 
             
                # Sessions command
         | 
| 400 397 | 
             
                sessions_parser = aggregate_subparsers.add_parser(
         | 
| 401 | 
            -
                     | 
| 402 | 
            -
                    help='List captured sessions'
         | 
| 398 | 
            +
                    "sessions", help="List captured sessions"
         | 
| 403 399 | 
             
                )
         | 
| 404 400 | 
             
                sessions_parser.add_argument(
         | 
| 405 | 
            -
                     | 
| 401 | 
            +
                    "--limit",
         | 
| 402 | 
            +
                    "-l",
         | 
| 406 403 | 
             
                    type=int,
         | 
| 407 404 | 
             
                    default=10,
         | 
| 408 | 
            -
                    help= | 
| 405 | 
            +
                    help="Maximum number of sessions to show (default: 10)",
         | 
| 409 406 | 
             
                )
         | 
| 410 | 
            -
             | 
| 407 | 
            +
             | 
| 411 408 | 
             
                # View command
         | 
| 412 409 | 
             
                view_parser = aggregate_subparsers.add_parser(
         | 
| 413 | 
            -
                     | 
| 414 | 
            -
                    help='View details of a specific session'
         | 
| 415 | 
            -
                )
         | 
| 416 | 
            -
                view_parser.add_argument(
         | 
| 417 | 
            -
                    'session_id',
         | 
| 418 | 
            -
                    help='Session ID or prefix to view'
         | 
| 410 | 
            +
                    "view", help="View details of a specific session"
         | 
| 419 411 | 
             
                )
         | 
| 412 | 
            +
                view_parser.add_argument("session_id", help="Session ID or prefix to view")
         | 
| 420 413 | 
             
                view_parser.add_argument(
         | 
| 421 | 
            -
                     | 
| 422 | 
            -
                    action='store_true',
         | 
| 423 | 
            -
                    help='Show event list'
         | 
| 414 | 
            +
                    "--show-events", "-e", action="store_true", help="Show event list"
         | 
| 424 415 | 
             
                )
         | 
| 425 416 | 
             
                view_parser.add_argument(
         | 
| 426 | 
            -
                     | 
| 417 | 
            +
                    "--event-limit",
         | 
| 427 418 | 
             
                    type=int,
         | 
| 428 419 | 
             
                    default=50,
         | 
| 429 | 
            -
                    help= | 
| 420 | 
            +
                    help="Maximum events to show (default: 50)",
         | 
| 430 421 | 
             
                )
         | 
| 431 422 | 
             
                view_parser.add_argument(
         | 
| 432 | 
            -
                     | 
| 433 | 
            -
                    action='store_true',
         | 
| 434 | 
            -
                    help='Show verbose event details'
         | 
| 423 | 
            +
                    "--verbose", "-v", action="store_true", help="Show verbose event details"
         | 
| 435 424 | 
             
                )
         | 
| 436 425 | 
             
                view_parser.add_argument(
         | 
| 437 | 
            -
                     | 
| 438 | 
            -
                    action='store_true',
         | 
| 439 | 
            -
                    help='Don\'t show final response'
         | 
| 426 | 
            +
                    "--no-response", action="store_true", help="Don't show final response"
         | 
| 440 427 | 
             
                )
         | 
| 441 | 
            -
             | 
| 428 | 
            +
             | 
| 442 429 | 
             
                # Export command
         | 
| 443 430 | 
             
                export_parser = aggregate_subparsers.add_parser(
         | 
| 444 | 
            -
                     | 
| 445 | 
            -
                    help='Export a session to file'
         | 
| 431 | 
            +
                    "export", help="Export a session to file"
         | 
| 446 432 | 
             
                )
         | 
| 433 | 
            +
                export_parser.add_argument("session_id", help="Session ID or prefix to export")
         | 
| 434 | 
            +
                export_parser.add_argument("--output", "-o", help="Output file path")
         | 
| 447 435 | 
             
                export_parser.add_argument(
         | 
| 448 | 
            -
                     | 
| 449 | 
            -
                     | 
| 436 | 
            +
                    "--format",
         | 
| 437 | 
            +
                    "-f",
         | 
| 438 | 
            +
                    choices=["json", "summary", "events"],
         | 
| 439 | 
            +
                    default="json",
         | 
| 440 | 
            +
                    help="Export format (default: json)",
         | 
| 450 441 | 
             
                )
         | 
| 451 | 
            -
             | 
| 452 | 
            -
             | 
| 453 | 
            -
                    help='Output file path'
         | 
| 454 | 
            -
                )
         | 
| 455 | 
            -
                export_parser.add_argument(
         | 
| 456 | 
            -
                    '--format', '-f',
         | 
| 457 | 
            -
                    choices=['json', 'summary', 'events'],
         | 
| 458 | 
            -
                    default='json',
         | 
| 459 | 
            -
                    help='Export format (default: json)'
         | 
| 460 | 
            -
                )
         | 
| 461 | 
            -
                
         | 
| 462 | 
            -
                aggregate_parser.set_defaults(func=aggregate_command)
         | 
| 442 | 
            +
             | 
| 443 | 
            +
                aggregate_parser.set_defaults(func=aggregate_command)
         |