claude-mpm 4.0.4__tar.gz → 4.0.9__tar.gz
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-4.0.9/BUILD_NUMBER +1 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/MANIFEST.in +2 -1
- {claude_mpm-4.0.4/src/claude_mpm.egg-info → claude_mpm-4.0.9}/PKG-INFO +1 -1
- claude_mpm-4.0.9/VERSION +1 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/pyproject.toml +1 -1
- claude_mpm-4.0.9/src/claude_mpm/VERSION +1 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/base_parser.py +34 -1
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/constants.py +4 -1
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/framework_loader.py +102 -14
- claude_mpm-4.0.9/src/claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm-4.0.9/src/claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/event-viewer.js +4 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/socket-client.js +7 -1
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/connection_pool.py +75 -12
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/hook_handler.py +63 -12
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/system_instructions_service.py +22 -7
- {claude_mpm-4.0.4 → claude_mpm-4.0.9/src/claude_mpm.egg-info}/PKG-INFO +1 -1
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm.egg-info/SOURCES.txt +1 -0
- claude_mpm-4.0.4/VERSION +0 -1
- claude_mpm-4.0.4/src/claude_mpm/VERSION +0 -1
- claude_mpm-4.0.4/src/claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm-4.0.4/src/claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/CLAUDE.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/LICENSE +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/README.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/claude-mpm +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/requirements.txt +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/scripts/ticket +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/setup.cfg +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/setup.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/__main__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/BASE_PM.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/INSTRUCTIONS.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/MEMORY.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/WORKFLOW.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/agent_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/agent_loader_integration.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/agents_metadata.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/async_agent_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/backups/INSTRUCTIONS.md +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/base_agent.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/base_agent_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/frontmatter_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/schema/agent_schema.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/system_agent_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/research_memory_efficient.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/code_analyzer.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/data_engineer.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/documentation.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/engineer.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/memory_manager.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/ops.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/project_organizer.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/qa.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/refactoring_engineer.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/research.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/security.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/ticketing.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/version_control.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/web_qa.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/agents/templates/web_ui.json +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/__main__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/agents.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/aggregate.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/cleanup.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/info.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp_command_router.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp_config_commands.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp_install_commands.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp_server_commands.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/mcp_tool_commands.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/memory.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/monitor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/run.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/run_config_checker.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/socketio_monitor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/commands/tickets.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/agents_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/config_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/mcp_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/memory_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/monitor_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/run_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/parsers/tickets_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/ticket_cli.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli/utils.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli_module/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli_module/args.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli_module/commands.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/cli_module/migration_example.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/config/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/config/agent_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/config/experimental_features.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/config/paths.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/config/socketio_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/agent_name_normalizer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/agent_registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/agent_session_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/base_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/cache.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/claude_runner.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/config_aliases.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/config_constants.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/constants.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/container.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/exceptions.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/factories.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/hook_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/hook_performance_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/injectable_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/interactive_session.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/interfaces.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/lazy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/logger.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/logging_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/minimal_framework_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/mixins.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/oneshot_session.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/optimized_agent_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/optimized_startup.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/pm_hook_interceptor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/service_registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/session_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/socketio_pool.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/tool_access_control.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/types.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/typing_utils.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/unified_agent_registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/unified_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/core/unified_paths.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/index.html +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/open_dashboard.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/agent-inference.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/event-processor.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/event-viewer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/export-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/hud-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/module-viewer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/session-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/socket-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/components/working-directory.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/dashboard.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/built/socket-client.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/css/dashboard.css +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/event-processor.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/export-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/session-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/components/working-directory.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/dist/dashboard.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/agent-inference.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/event-processor.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/export-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/hud-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/module-viewer.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/session-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/socket-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/working-directory.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/dashboard.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/extension-error-handler.js +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/templates/index.html +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/test_dashboard.html +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/experimental/cli_enhancements.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/generators/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/generators/agent_profile_generator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/base_hook.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/event_handlers.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/hook_wrapper.sh +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/memory_integration.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/response_tracking.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/claude_hooks/tool_analysis.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/memory_integration_hook.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/tool_call_interceptor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/hooks/validation_hooks.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/init.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/models/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/models/agent_definition.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/models/agent_session.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/scripts/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/scripts/socketio_daemon.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/scripts/socketio_server_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/scripts/start_activity_logging.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agent_capabilities_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_config_provider.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_configuration_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_definition_factory.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_deployment.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_discovery_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_environment_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_filesystem_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_format_converter.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_metrics_collector.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_template_builder.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_version_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agent_versioning.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/agents_directory_resolver.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/async_agent_deployment.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/config/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/config/deployment_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/config/deployment_config_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/deployment_config_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/deployment_type_detector.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/facade/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/facade/deployment_facade.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/interface_adapter.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/lifecycle_health_checker.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/processors/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/processors/agent_processor.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/results/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/results/deployment_metrics.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/results/deployment_result_builder.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/base_strategy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/project_strategy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/strategy_selector.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/system_strategy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/strategies/user_strategy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/system_instructions_deployer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/validation/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/validation/agent_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/validation/deployment_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/validation/template_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/deployment/validation/validation_result.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/loading/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/loading/agent_profile_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/loading/base_agent_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/loading/framework_agent_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/management/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/management/agent_capabilities_generator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/management/agent_management_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/agent_memory_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/agent_persistence_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/analyzer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/content_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/memory/template_generator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/registry/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/registry/deployed_agent_discovery.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/agents/registry/modification_tracker.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/async_session_logger.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/claude_session_logger.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/command_handler_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/communication/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/base.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces/agent.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces/communication.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces/infrastructure.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces/service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/core/interfaces.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/event_aggregator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/exceptions.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/content_assembler.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/content_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/deployment_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/header.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/section_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/framework_claude_md_generator/version_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/hook_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/infrastructure/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/infrastructure/context_preservation.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/infrastructure/daemon_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/infrastructure/logging.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/infrastructure/monitoring.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/config/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/config/config_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/config/config_schema.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/config/configuration.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/core/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/core/base.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/core/exceptions.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/core/interfaces.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/main.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/registry/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/server/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/builder.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/cache/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/cache/shared_prompt_cache.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/cache/simple_cache.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/indexed_memory.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/optimizer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory/router.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/memory_hook_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/port_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/project/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/project/analyzer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/project/registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/recovery_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/response_tracker.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/runner_configuration_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/session_management_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/client_proxy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/base.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/connection.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/file.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/git.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/hook.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/memory.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/project.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/handlers/registry.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/server/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/server/broadcaster.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/server/core.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio/server/main.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio_client_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/socketio_server.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/subprocess_launcher_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/ticket_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/utility_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/branch_strategy.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/conflict_resolution.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/git_operations.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/semantic_versioning.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_control/version_parser.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/services/version_service.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/storage/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/storage/state_storage.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/ticket_wrapper.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/agent_dependency_loader.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/config_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/console.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/dependency_cache.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/dependency_manager.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/dependency_strategies.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/environment_context.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/error_handler.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/file_utils.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/framework_detection.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/import_migration_example.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/imports.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/path_operations.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/robust_installer.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/session_logging.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/utils/subprocess_utils.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/validation/__init__.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/validation/agent_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/validation/frontmatter_validator.py +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm.egg-info/dependency_links.txt +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm.egg-info/entry_points.txt +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm.egg-info/requires.txt +0 -0
- {claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
285
|
|
@@ -7,8 +7,9 @@ include CLAUDE.md
|
|
|
7
7
|
include requirements.txt
|
|
8
8
|
include requirements-dev.txt
|
|
9
9
|
|
|
10
|
-
# Include version
|
|
10
|
+
# Include version and build files
|
|
11
11
|
include VERSION
|
|
12
|
+
include BUILD_NUMBER
|
|
12
13
|
include src/claude_mpm/VERSION
|
|
13
14
|
|
|
14
15
|
# Include all agent templates and instructions
|
claude_mpm-4.0.9/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
4.0.9
|
|
@@ -16,6 +16,37 @@ from typing import List, Optional
|
|
|
16
16
|
from ...constants import CLICommands, CLIPrefix, LogLevel
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def _get_enhanced_version(base_version: str) -> str:
|
|
20
|
+
"""
|
|
21
|
+
Get enhanced version string with build number if available.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
base_version: Base version string (e.g., "4.0.8")
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Enhanced version string with build number if available
|
|
28
|
+
"""
|
|
29
|
+
try:
|
|
30
|
+
# Try to use VersionService for enhanced version display
|
|
31
|
+
from ...services.version_service import VersionService
|
|
32
|
+
|
|
33
|
+
version_service = VersionService()
|
|
34
|
+
enhanced = version_service.get_version()
|
|
35
|
+
|
|
36
|
+
# If we got an enhanced version (with build number), use it
|
|
37
|
+
# Remove the 'v' prefix since argparse will add the program name
|
|
38
|
+
if enhanced and enhanced.startswith('v'):
|
|
39
|
+
enhanced = enhanced[1:] # Remove 'v' prefix
|
|
40
|
+
|
|
41
|
+
if enhanced and enhanced != base_version:
|
|
42
|
+
return enhanced
|
|
43
|
+
except Exception:
|
|
44
|
+
# If anything fails, fall back to base version
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
return base_version
|
|
48
|
+
|
|
49
|
+
|
|
19
50
|
def add_common_arguments(parser: argparse.ArgumentParser, version: str = None) -> None:
|
|
20
51
|
"""
|
|
21
52
|
Add common arguments that apply to all commands.
|
|
@@ -29,8 +60,10 @@ def add_common_arguments(parser: argparse.ArgumentParser, version: str = None) -
|
|
|
29
60
|
"""
|
|
30
61
|
# Version - only add to main parser, not subparsers
|
|
31
62
|
if version is not None:
|
|
63
|
+
# Use enhanced version display with build number if available
|
|
64
|
+
enhanced_version = _get_enhanced_version(version)
|
|
32
65
|
parser.add_argument(
|
|
33
|
-
"--version", action="version", version=f"%(prog)s {
|
|
66
|
+
"--version", action="version", version=f"%(prog)s {enhanced_version}"
|
|
34
67
|
)
|
|
35
68
|
|
|
36
69
|
# Logging arguments
|
|
@@ -61,9 +61,11 @@ class FrameworkLoader:
|
|
|
61
61
|
|
|
62
62
|
# Otherwise check common locations for claude-mpm
|
|
63
63
|
candidates = [
|
|
64
|
+
# Current directory (if we're already in claude-mpm)
|
|
65
|
+
Path.cwd(),
|
|
64
66
|
# Development location
|
|
65
67
|
Path.home() / "Projects" / "claude-mpm",
|
|
66
|
-
# Current directory
|
|
68
|
+
# Current directory subdirectory
|
|
67
69
|
Path.cwd() / "claude-mpm",
|
|
68
70
|
]
|
|
69
71
|
|
|
@@ -256,29 +258,102 @@ class FrameworkLoader:
|
|
|
256
258
|
content["project_memory"] = "system"
|
|
257
259
|
self.logger.info("Using system MEMORY.md")
|
|
258
260
|
|
|
261
|
+
def _get_deployed_agents(self) -> set:
|
|
262
|
+
"""
|
|
263
|
+
Get a set of deployed agent names from .claude/agents/ directories.
|
|
264
|
+
|
|
265
|
+
Returns:
|
|
266
|
+
Set of agent names (file stems) that are deployed
|
|
267
|
+
"""
|
|
268
|
+
deployed = set()
|
|
269
|
+
|
|
270
|
+
# Check multiple locations for deployed agents
|
|
271
|
+
agents_dirs = [
|
|
272
|
+
Path.cwd() / ".claude" / "agents", # Project-specific agents
|
|
273
|
+
Path.home() / ".claude" / "agents", # User's system agents
|
|
274
|
+
]
|
|
275
|
+
|
|
276
|
+
for agents_dir in agents_dirs:
|
|
277
|
+
if agents_dir.exists():
|
|
278
|
+
for agent_file in agents_dir.glob("*.md"):
|
|
279
|
+
if not agent_file.name.startswith("."):
|
|
280
|
+
# Use stem to get agent name without extension
|
|
281
|
+
deployed.add(agent_file.stem)
|
|
282
|
+
self.logger.debug(f"Found deployed agent: {agent_file.stem} in {agents_dir}")
|
|
283
|
+
|
|
284
|
+
self.logger.debug(f"Total deployed agents found: {len(deployed)}")
|
|
285
|
+
return deployed
|
|
286
|
+
|
|
259
287
|
def _load_actual_memories(self, content: Dict[str, Any]) -> None:
|
|
260
288
|
"""
|
|
261
|
-
Load actual
|
|
289
|
+
Load actual memories from .claude-mpm/memories/ directory.
|
|
262
290
|
|
|
263
|
-
|
|
264
|
-
|
|
291
|
+
This loads:
|
|
292
|
+
1. PM memories from PM.md (always loaded)
|
|
293
|
+
2. Agent memories from <agent>.md (only if agent is deployed)
|
|
265
294
|
|
|
266
295
|
Args:
|
|
267
296
|
content: Dictionary to update with actual memories
|
|
268
297
|
"""
|
|
269
|
-
|
|
270
|
-
|
|
298
|
+
memories_dir = Path.cwd() / ".claude-mpm" / "memories"
|
|
299
|
+
|
|
300
|
+
# Log the memory loading process
|
|
301
|
+
if memories_dir.exists():
|
|
302
|
+
self.logger.info(f"Loading memory files from: {memories_dir}")
|
|
303
|
+
else:
|
|
304
|
+
self.logger.debug(f"No memories directory found at: {memories_dir}")
|
|
305
|
+
return
|
|
306
|
+
|
|
307
|
+
# Check for deployed agents
|
|
308
|
+
deployed_agents = self._get_deployed_agents()
|
|
309
|
+
|
|
310
|
+
# Track loading statistics
|
|
311
|
+
loaded_count = 0
|
|
312
|
+
skipped_count = 0
|
|
313
|
+
|
|
314
|
+
# Load PM memories (always loaded)
|
|
315
|
+
pm_memory_path = memories_dir / "PM.md"
|
|
316
|
+
if pm_memory_path.exists():
|
|
271
317
|
loaded_content = self._try_load_file(
|
|
272
|
-
|
|
318
|
+
pm_memory_path, "PM memory"
|
|
273
319
|
)
|
|
274
320
|
if loaded_content:
|
|
275
321
|
content["actual_memories"] = loaded_content
|
|
276
|
-
self.logger.info(f"Loaded PM memories from: {memories_path}")
|
|
277
|
-
# Log memory size for monitoring
|
|
278
322
|
memory_size = len(loaded_content.encode('utf-8'))
|
|
279
|
-
self.logger.
|
|
323
|
+
self.logger.info(f"Loaded PM memory: {pm_memory_path} ({memory_size:,} bytes)")
|
|
324
|
+
loaded_count += 1
|
|
280
325
|
else:
|
|
281
|
-
self.logger.debug(f"No PM
|
|
326
|
+
self.logger.debug(f"No PM memory found at: {pm_memory_path}")
|
|
327
|
+
|
|
328
|
+
# Load agent memories (only for deployed agents)
|
|
329
|
+
for memory_file in memories_dir.glob("*.md"):
|
|
330
|
+
# Skip PM.md as we already handled it
|
|
331
|
+
if memory_file.name == "PM.md":
|
|
332
|
+
continue
|
|
333
|
+
|
|
334
|
+
# Extract agent name from file
|
|
335
|
+
agent_name = memory_file.stem
|
|
336
|
+
|
|
337
|
+
# Check if agent is deployed
|
|
338
|
+
if agent_name in deployed_agents:
|
|
339
|
+
loaded_content = self._try_load_file(
|
|
340
|
+
memory_file, f"agent memory: {agent_name}"
|
|
341
|
+
)
|
|
342
|
+
if loaded_content:
|
|
343
|
+
# Store agent memories separately (for future use)
|
|
344
|
+
if "agent_memories" not in content:
|
|
345
|
+
content["agent_memories"] = {}
|
|
346
|
+
content["agent_memories"][agent_name] = loaded_content
|
|
347
|
+
memory_size = len(loaded_content.encode('utf-8'))
|
|
348
|
+
self.logger.info(f"Loaded agent memory: {memory_file.name} (deployed agent found, {memory_size:,} bytes)")
|
|
349
|
+
loaded_count += 1
|
|
350
|
+
else:
|
|
351
|
+
self.logger.info(f"Skipped agent memory: {memory_file.name} (agent not deployed)")
|
|
352
|
+
skipped_count += 1
|
|
353
|
+
|
|
354
|
+
# Log summary
|
|
355
|
+
if loaded_count > 0 or skipped_count > 0:
|
|
356
|
+
self.logger.info(f"Memory loading complete: {loaded_count} memories loaded, {skipped_count} skipped")
|
|
282
357
|
|
|
283
358
|
def _load_single_agent(
|
|
284
359
|
self, agent_file: Path
|
|
@@ -639,10 +714,23 @@ Extract tickets from these patterns:
|
|
|
639
714
|
import yaml
|
|
640
715
|
|
|
641
716
|
# Read directly from deployed agents in .claude/agents/
|
|
642
|
-
|
|
717
|
+
# Check multiple locations for deployed agents
|
|
718
|
+
# Priority order: project > user home > fallback
|
|
719
|
+
agents_dirs = [
|
|
720
|
+
Path.cwd() / ".claude" / "agents", # Project-specific agents
|
|
721
|
+
Path.home() / ".claude" / "agents", # User's system agents
|
|
722
|
+
]
|
|
723
|
+
|
|
724
|
+
agents_dir = None
|
|
725
|
+
for potential_dir in agents_dirs:
|
|
726
|
+
if potential_dir.exists() and any(potential_dir.glob("*.md")):
|
|
727
|
+
agents_dir = potential_dir
|
|
728
|
+
self.logger.debug(f"Found agents directory at: {agents_dir}")
|
|
729
|
+
break
|
|
730
|
+
|
|
643
731
|
|
|
644
|
-
if not agents_dir
|
|
645
|
-
self.logger.warning("No .claude/agents directory found")
|
|
732
|
+
if not agents_dir:
|
|
733
|
+
self.logger.warning(f"No .claude/agents directory found in any location: {agents_dirs}")
|
|
646
734
|
return self._get_fallback_capabilities()
|
|
647
735
|
|
|
648
736
|
# Build capabilities section
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
class e{constructor(e,t){this.container=document.getElementById(e),this.socketClient=t,this.events=[],this.filteredEvents=[],this.selectedEventIndex=-1,this.filteredEventElements=[],this.autoScroll=!0,this.searchFilter="",this.typeFilter="",this.sessionFilter="",this.eventTypeCount={},this.availableEventTypes=new Set,this.errorCount=0,this.eventsThisMinute=0,this.lastMinute=(new Date).getMinutes(),this.init()}init(){this.setupEventHandlers(),this.setupKeyboardNavigation(),this.socketClient.onEventUpdate((e,t)=>{this.events=Array.isArray(e)?e:[],this.updateDisplay()})}setupEventHandlers(){const e=document.getElementById("events-search-input");e&&e.addEventListener("input",e=>{this.searchFilter=e.target.value.toLowerCase(),this.applyFilters()});const t=document.getElementById("events-type-filter");t&&t.addEventListener("change",e=>{this.typeFilter=e.target.value,this.applyFilters()})}setupKeyboardNavigation(){console.log("EventViewer: Keyboard navigation handled by unified Dashboard system")}handleArrowNavigation(e){if(0===this.filteredEventElements.length)return;let t=this.selectedEventIndex+e;t>=this.filteredEventElements.length?t=0:t<0&&(t=this.filteredEventElements.length-1),this.showEventDetails(t)}applyFilters(){this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized, using empty array"),this.events=[]),this.filteredEvents=this.events.filter(e=>{if(this.searchFilter){if(![e.type||"",e.subtype||"",JSON.stringify(e.data||{})].join(" ").toLowerCase().includes(this.searchFilter))return!1}if(this.typeFilter){const t=e.type&&""!==e.type.trim()?e.type:"";if((e.subtype&&t?`${t}.${e.subtype}`:t)!==this.typeFilter)return!1}return!(this.sessionFilter&&""!==this.sessionFilter&&(!e.data||e.data.session_id!==this.sessionFilter))}),this.renderEvents(),this.updateMetrics()}updateEventTypeDropdown(){const e=document.getElementById("events-type-filter");if(!e)return;const t=new Set;this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized in updateEventTypeDropdown"),this.events=[]),this.events.forEach(e=>{if(e.type&&""!==e.type.trim()){const n=e.subtype?`${e.type}.${e.subtype}`:e.type;t.add(n)}});const n=Array.from(t).sort(),s=Array.from(this.availableEventTypes).sort();if(JSON.stringify(n)===JSON.stringify(s))return;this.availableEventTypes=t;const i=e.value;e.innerHTML='<option value="">All Events</option>';Array.from(t).sort().forEach(t=>{const n=document.createElement("option");n.value=t,n.textContent=t,e.appendChild(n)}),i&&t.has(i)?e.value=i:i&&!t.has(i)&&(e.value="",this.typeFilter="")}updateDisplay(){this.updateEventTypeDropdown(),this.applyFilters()}renderEvents(){const e=document.getElementById("events-list");if(!e)return;if(0===this.filteredEvents.length)return e.innerHTML=`\n <div class="no-events">\n ${0===this.events.length?"Connect to Socket.IO server to see events...":"No events match current filters..."}\n </div>\n `,void(this.filteredEventElements=[]);const t=this.filteredEvents.map((e,t)=>{const n=new Date(e.timestamp).toLocaleTimeString();return`\n <div class="event-item single-row ${e.type?`event-${e.type}`:"event-default"} ${t===this.selectedEventIndex?"selected":""}"\n onclick="eventViewer.showEventDetails(${t})"\n data-index="${t}">\n <span class="event-single-row-content">\n <span class="event-content-main">${this.formatSingleRowEventContent(e)}</span>\n <span class="event-timestamp">${n}</span>\n </span>\n ${this.createInlineEditDiffViewer(e,t)}\n </div>\n `}).join("");e.innerHTML=t,this.filteredEventElements=Array.from(e.querySelectorAll(".event-item")),window.dashboard&&"events"===window.dashboard.currentTab&&window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.items=this.filteredEventElements),this.autoScroll&&this.filteredEvents.length>0&&(e.scrollTop=e.scrollHeight)}formatEventType(e){return e.type&&e.subtype?e.type===e.subtype?e.type:`${e.type}.${e.subtype}`:e.type?e.type:e.originalEventName?e.originalEventName:"unknown"}formatEventData(e){if(!e.data)return"No data";switch(e.type){case"session":return this.formatSessionEvent(e);case"claude":return this.formatClaudeEvent(e);case"agent":return this.formatAgentEvent(e);case"hook":return this.formatHookEvent(e);case"todo":return this.formatTodoEvent(e);case"memory":return this.formatMemoryEvent(e);case"log":return this.formatLogEvent(e);default:return this.formatGenericEvent(e)}}formatSessionEvent(e){const t=e.data;return"started"===e.subtype?`<strong>Session started:</strong> ${t.session_id||"Unknown"}`:"ended"===e.subtype?`<strong>Session ended:</strong> ${t.session_id||"Unknown"}`:`<strong>Session:</strong> ${JSON.stringify(t)}`}formatClaudeEvent(e){const t=e.data;if("request"===e.subtype){const e=t.prompt||t.message||"";return`<strong>Request:</strong> ${e.length>100?e.substring(0,100)+"...":e}`}if("response"===e.subtype){const e=t.response||t.content||"";return`<strong>Response:</strong> ${e.length>100?e.substring(0,100)+"...":e}`}return`<strong>Claude:</strong> ${JSON.stringify(t)}`}formatAgentEvent(e){const t=e.data;return"loaded"===e.subtype?`<strong>Agent loaded:</strong> ${t.agent_type||t.name||"Unknown"}`:"executed"===e.subtype?`<strong>Agent executed:</strong> ${t.agent_type||t.name||"Unknown"}`:`<strong>Agent:</strong> ${JSON.stringify(t)}`}formatHookEvent(e){const t=e.data,n=t.event_type||e.subtype||"unknown";switch(n){case"user_prompt":const s=t.prompt_text||t.prompt_preview||"";return`<strong>User Prompt:</strong> ${(s.length>80?s.substring(0,80)+"...":s)||"No prompt text"}`;case"pre_tool":const i=t.tool_name||"Unknown tool";return`<strong>Pre-Tool (${t.operation_type||"operation"}):</strong> ${i}`;case"post_tool":const o=t.tool_name||"Unknown tool";return`<strong>Post-Tool (${t.success?"success":t.status||"failed"}):</strong> ${o}${t.duration_ms?` (${t.duration_ms}ms)`:""}`;case"notification":return`<strong>Notification (${t.notification_type||"notification"}):</strong> ${t.message_preview||t.message||"No message"}`;case"stop":const r=t.reason||"unknown";return`<strong>Stop (${t.stop_type||"normal"}):</strong> ${r}`;case"subagent_stop":return`<strong>Subagent Stop (${t.agent_type||"unknown agent"}):</strong> ${t.reason||"unknown"}`;default:const a=t.hook_name||t.name||t.event_type||"Unknown";return`<strong>Hook ${e.subtype||n}:</strong> ${a}`}}formatTodoEvent(e){const t=e.data;if(t.todos&&Array.isArray(t.todos)){const e=t.todos.length;return`<strong>Todo updated:</strong> ${e} item${1!==e?"s":""}`}return`<strong>Todo:</strong> ${JSON.stringify(t)}`}formatMemoryEvent(e){const t=e.data;return`<strong>Memory ${t.operation||"unknown"}:</strong> ${t.key||"Unknown key"}`}formatLogEvent(e){const t=e.data,n=t.level||"info",s=t.message||"",i=s.length>80?s.substring(0,80)+"...":s;return`<strong>[${n.toUpperCase()}]</strong> ${i}`}formatGenericEvent(e){const t=e.data;return"string"==typeof t?t.length>100?t.substring(0,100)+"...":t:JSON.stringify(t)}formatSingleRowEventContent(e){const t=this.formatEventType(e),n=e.data||{};let s="",i="";switch(e.type){case"hook":const t=e.tool_name||n.tool_name||"Unknown",o=e.subtype||"Unknown",r=this.getHookDisplayName(o,n);i=this.getEventCategory(e),s=`${r} (${i}): ${t}`;break;case"agent":i="agent_operations",s=`${e.subagent_type||n.subagent_type||"PM"} ${e.subtype||"action"}`;break;case"todo":i="task_management",s=`TodoWrite (${n.todos?n.todos.length:0} items)`;break;case"memory":i="memory_operations",s=`${n.operation||"unknown"} ${n.key||"unknown"}`;break;case"session":i="session_management",s=`Session ${e.subtype||"unknown"}`;break;case"claude":i="claude_interactions",s=`Claude ${e.subtype||"interaction"}`;break;default:i="general",s=e.type||"Unknown Event"}return`${t} ${s}`}getHookDisplayName(e,t){const n={pre_tool:"Pre-Tool",post_tool:"Post-Tool",user_prompt:"User-Prompt",stop:"Stop",subagent_stop:"Subagent-Stop",notification:"Notification"};if(n[e])return n[e];return String(e||"unknown").replace(/_/g," ")}getEventCategory(e){const t=e.data||{},n=e.tool_name||t.tool_name||"";return["Read","Write","Edit","MultiEdit"].includes(n)?"file_operations":["Bash","grep","Glob"].includes(n)?"system_operations":"TodoWrite"===n?"task_management":"Task"===n?"agent_delegation":"stop"===e.subtype||"subagent_stop"===e.subtype?"session_control":"general"}showEventDetails(e){if(!this.filteredEvents||!Array.isArray(this.filteredEvents))return void console.warn("EventViewer: filteredEvents array is not initialized");if(e<0||e>=this.filteredEvents.length)return;this.selectedEventIndex=e;const t=this.filteredEvents[e];window.dashboard&&(window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.selectedIndex=e),window.dashboard.selectCard&&window.dashboard.selectCard("events",e,"event",t)),this.filteredEventElements.forEach((t,n)=>{t.classList.toggle("selected",n===e)}),document.dispatchEvent(new CustomEvent("eventSelected",{detail:{event:t,index:e}}));const n=this.filteredEventElements[e];n&&n.scrollIntoView({behavior:"smooth",block:"nearest"})}clearSelection(){this.selectedEventIndex=-1,this.filteredEventElements.forEach(e=>{e.classList.remove("selected")}),window.dashboard&&(window.dashboard.tabNavigation&&window.dashboard.tabNavigation.events&&(window.dashboard.tabNavigation.events.selectedIndex=-1),window.dashboard.clearCardSelection&&window.dashboard.clearCardSelection()),document.dispatchEvent(new CustomEvent("eventSelectionCleared"))}updateMetrics(){this.eventTypeCount={},this.errorCount=0,this.events&&Array.isArray(this.events)||(console.warn("EventViewer: events array is not initialized in updateMetrics"),this.events=[]),this.events.forEach(e=>{const t=e.type||"unknown";this.eventTypeCount[t]=(this.eventTypeCount[t]||0)+1,"log"===e.type&&e.data&&["error","critical"].includes(e.data.level)&&this.errorCount++});const e=(new Date).getMinutes();e!==this.lastMinute&&(this.lastMinute=e,this.eventsThisMinute=0);const t=new Date(Date.now()-6e4);this.eventsThisMinute=this.events.filter(e=>new Date(e.timestamp)>t).length,this.updateMetricsUI()}updateMetricsUI(){const e=document.getElementById("total-events"),t=document.getElementById("events-per-minute"),n=document.getElementById("unique-types"),s=document.getElementById("error-count");e&&(e.textContent=this.events.length),t&&(t.textContent=this.eventsThisMinute),n&&(n.textContent=Object.keys(this.eventTypeCount).length),s&&(s.textContent=this.errorCount)}exportEvents(){const e=JSON.stringify(this.filteredEvents,null,2),t=new Blob([e],{type:"application/json"}),n=URL.createObjectURL(t),s=document.createElement("a");s.href=n,s.download=`claude-mpm-events-${(new Date).toISOString().split("T")[0]}.json`,s.click(),URL.revokeObjectURL(n)}clearEvents(){this.socketClient.clearEvents(),this.selectedEventIndex=-1,this.updateDisplay()}setSessionFilter(e){this.sessionFilter=e,this.applyFilters()}getFilters(){return{search:this.searchFilter,type:this.typeFilter,session:this.sessionFilter}}getFilteredEvents(){return this.filteredEvents}getAllEvents(){return this.events}createInlineEditDiffViewer(e,t){const n=e.data||{},s=e.tool_name||n.tool_name||"";if(!["Edit","MultiEdit"].includes(s))return"";let i=[];if("Edit"===s){const t=e.tool_parameters||n.tool_parameters||{};t.old_string&&t.new_string&&i.push({old_string:t.old_string,new_string:t.new_string,file_path:t.file_path||"unknown"})}else if("MultiEdit"===s){const t=e.tool_parameters||n.tool_parameters||{};t.edits&&Array.isArray(t.edits)&&(i=t.edits.map(e=>({...e,file_path:t.file_path||"unknown"})))}if(0===i.length)return"";const o=`edit-diff-${t}`,r=i.length>1;let a="";return i.forEach((e,t)=>{const n=this.createDiffHtml(e.old_string,e.new_string);a+=`\n <div class="edit-diff-section">\n ${r?`<div class="edit-diff-header">Edit ${t+1}</div>`:""}\n <div class="diff-content">${n}</div>\n </div>\n `}),`\n <div class="inline-edit-diff-viewer">\n <div class="diff-toggle-header" onclick="eventViewer.toggleEditDiff('${o}', event)">\n <span class="diff-toggle-icon">📋</span>\n <span class="diff-toggle-text">Show ${r?i.length+" edits":"edit"}</span>\n <span class="diff-toggle-arrow">▼</span>\n </div>\n <div id="${o}" class="diff-content-container" style="display: none;">\n ${a}\n </div>\n </div>\n `}createDiffHtml(e,t){const n=e.split("\n"),s=t.split("\n");let i="",o=0,r=0;for(;o<n.length||r<s.length;){const e=o<n.length?n[o]:null,t=r<s.length?s[r]:null;null===e?(i+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,r++):null===t?(i+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,o++):e===t?(i+=`<div class="diff-line diff-unchanged"> ${this.escapeHtml(e)}</div>`,o++,r++):(i+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,i+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,o++,r++)}return`<div class="diff-container">${i}</div>`}toggleEditDiff(e,t){t.stopPropagation();const n=document.getElementById(e),s=t.currentTarget.querySelector(".diff-toggle-arrow");if(n){const e="none"!==n.style.display;n.style.display=e?"none":"block",s&&(s.textContent=e?"▼":"▲")}}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}}window.EventViewer=e;class t{constructor(e,t){this.eventViewer=e,this.agentInference=t,this.agentEvents=[],this.filteredAgentEvents=[],this.filteredToolEvents=[],this.filteredFileEvents=[],this.selectedSessionId=null,this.fileTrackingCache=new Map,this.trackingCheckTimeout=3e4,console.log("Event processor initialized")}getFilteredEventsForTab(e){const t=this.eventViewer.events;console.log(`getFilteredEventsForTab(${e}) - using RAW events: ${t.length} total`);const n=window.sessionManager;if(n&&n.selectedSessionId){const e=n.getEventsForSession(n.selectedSessionId);return console.log(`Filtering by session ${n.selectedSessionId}: ${e.length} events`),e}return t}applyAgentsFilters(e){const t=document.getElementById("agents-search-input"),n=document.getElementById("agents-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(e=>{if(s){if(![e.agentName||"",e.type||"",e.isImplied?"implied":"explicit"].join(" ").toLowerCase().includes(s))return!1}if(i){if(!(e.agentName||"unknown").toLowerCase().includes(i.toLowerCase()))return!1}return!0})}applyToolsFilters(e){const t=document.getElementById("tools-search-input"),n=document.getElementById("tools-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(e=>{if(s){if(![e.tool_name||"",e.agent_type||"",e.type||"",e.subtype||""].join(" ").toLowerCase().includes(s))return!1}if(i){if((e.tool_name||"")!==i)return!1}return!0})}applyToolCallFilters(e){const t=document.getElementById("tools-search-input"),n=document.getElementById("tools-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(([e,t])=>{if(s){if(![t.tool_name||"",t.agent_type||"","tool_call"].join(" ").toLowerCase().includes(s))return!1}if(i){if((t.tool_name||"")!==i)return!1}return!0})}applyFilesFilters(e){const t=document.getElementById("files-search-input"),n=document.getElementById("files-type-filter"),s=t?t.value.toLowerCase():"",i=n?n.value:"";return e.filter(([e,t])=>{if(this.selectedSessionId){const e=t.operations.filter(e=>e.sessionId===this.selectedSessionId);if(0===e.length)return!1;t={...t,operations:e,lastOperation:e[e.length-1]?.timestamp||t.lastOperation}}if(s){if(![e,...t.operations.map(e=>e.operation),...t.operations.map(e=>e.agent)].join(" ").toLowerCase().includes(s))return!1}if(i){if(!t.operations.map(e=>e.operation).includes(i))return!1}return!0})}extractOperation(e){if(!e)return"unknown";const t=e.toLowerCase();return t.includes("read")?"read":t.includes("write")?"write":t.includes("edit")?"edit":t.includes("create")?"create":t.includes("delete")?"delete":t.includes("move")||t.includes("rename")?"move":"other"}extractToolFromHook(e){if(!e)return"";const t=e.match(/^(?:Pre|Post)(.+)Use$/);return t?t[1]:""}extractToolFromSubtype(e){if(!e)return"";if(e.includes("_")){return e.split("_")[0]||""}return e}extractToolTarget(e,t,n){const s=t||n||{};switch(e?.toLowerCase()){case"read":case"write":case"edit":return s.file_path||s.path||"";case"bash":return s.command||"";case"grep":return s.pattern||"";case"task":return s.subagent_type||s.agent_type||"";default:const e=Object.keys(s),t=["path","file_path","command","pattern","query","target"];for(const n of t)if(s[n])return s[n];return e.length>0?`${e[0]}: ${s[e[0]]}`:""}}generateAgentHTML(e){const t=this.agentInference.getUniqueAgentInstances();return this.applyAgentsFilters(t).map((e,t)=>{const n=e.agentName,s=this.formatTimestamp(e.firstTimestamp||e.timestamp),i=e.isImplied?"implied":"explicit",o=e.totalEventCount||e.eventCount||0;return`\n <div class="event-item single-row event-agent" onclick="${`dashboard.selectCard('agents', ${t}, 'agent_instance', '${e.id}'); dashboard.showAgentInstanceDetails('${e.id}');`}">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${n} (${i}, ${o} events)`}</span>\n <span class="event-timestamp">${s}</span>\n </span>\n </div>\n `}).join("")}generateToolHTML(e){return this.applyToolCallFilters(e).map(([e,t],n)=>{const s=t.tool_name||"Unknown",i=t.agent_type||"Unknown",o=this.formatTimestamp(t.timestamp);return`\n <div class="event-item single-row event-tool ${"completed"===(t.post_event?"completed":"pending")?"status-success":"status-pending"}" onclick="dashboard.selectCard('tools', ${n}, 'toolCall', '${e}'); dashboard.showToolCallDetails('${e}')">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${s} (${"pm"===i.toLowerCase()?"pm":i})`}</span>\n <span class="event-timestamp">${o}</span>\n </span>\n </div>\n `}).join("")}generateFileHTML(e){return this.applyFilesFilters(e).map(([e,t],n)=>{const s=t.operations.map(e=>e.operation),i=this.formatTimestamp(t.lastOperation),o={};s.forEach(e=>{o[e]=(o[e]||0)+1});const r=Object.entries(o).map(([e,t])=>`${e}(${t})`).join(", "),a=[...new Set(t.operations.map(e=>e.agent))],l=a.length>1?`by ${a.length} agents`:`by ${a[0]||"unknown"}`;return`\n <div class="event-item single-row file-item" onclick="dashboard.selectCard('files', ${n}, 'file', '${e}'); dashboard.showFileDetails('${e}')">\n <span class="event-single-row-content">\n <span class="event-content-main">${`${this.getRelativeFilePath(e)} ${r} ${l}`}</span>\n <span class="event-timestamp">${i}</span>\n </span>\n </div>\n `}).join("")}getFileOperationIcon(e){return e.includes("write")||e.includes("create")?"📝":e.includes("edit")?"✏️":e.includes("read")?"👁️":e.includes("delete")?"🗑️":e.includes("move")?"📦":"📄"}getRelativeFilePath(e){if(!e)return"";const t=e.split("/");return t.length>3?".../"+t.slice(-2).join("/"):e}formatTimestamp(e){if(!e)return"";return new Date(e).toLocaleTimeString()}setSelectedSessionId(e){this.selectedSessionId=e}getSelectedSessionId(){return this.selectedSessionId}getUniqueToolInstances(e){return this.applyToolCallFilters(e)}getUniqueFileInstances(e){return this.applyFilesFilters(e)}async isFileTracked(e,t){const n=`${t}:${e}`,s=Date.now(),i=this.fileTrackingCache.get(n);if(i&&s-i.timestamp<this.trackingCheckTimeout)return i.is_tracked;try{const i=window.socket;return i?new Promise(o=>{const r=t=>{if(t.file_path===e){const e=t.success&&t.is_tracked;this.fileTrackingCache.set(n,{is_tracked:e,timestamp:s}),i.off("file_tracked_response",r),o(e)}};i.on("file_tracked_response",r),i.emit("check_file_tracked",{file_path:e,working_dir:t}),setTimeout(()=>{i.off("file_tracked_response",r),o(!1)},5e3)}):(console.warn("No socket connection available for git tracking check"),!1)}catch(o){return console.error("Error checking file tracking status:",o),!1}}generateGitDiffIcon(e,t,n){const s=`git-icon-${e.replace(/[^a-zA-Z0-9]/g,"-")}-${t}`,i=`\n <span id="${s}" class="git-diff-icon"\n onclick="event.stopPropagation(); showGitDiffModal('${e}', '${t}')"\n title="View git diff for this file operation"\n style="margin-left: 8px; cursor: pointer; font-size: 16px;">\n 📋\n </span>\n `;return this.isFileTracked(e,n).then(e=>{const t=document.getElementById(s);t&&(e?(t.innerHTML="📋",t.title="View git diff for this file operation",t.classList.add("tracked-file")):(t.innerHTML="📋❌",t.title="File not tracked by git - click to see details",t.classList.add("untracked-file")))}).catch(e=>{console.error("Error updating git diff icon:",e)}),i}showAgentInstanceDetails(e){const t=this.agentInference.getPMDelegations().get(e);if(!t)return void console.error("Agent instance not found:",e);console.log("Showing agent instance details for:",e,t);const n=`\n <div class="agent-instance-details">\n <h3>Agent Instance: ${t.agentName}</h3>\n <p><strong>Type:</strong> ${t.isImplied?"Implied PM Delegation":"Explicit PM Delegation"}</p>\n <p><strong>Start Time:</strong> ${this.formatTimestamp(t.timestamp)}</p>\n <p><strong>Event Count:</strong> ${t.agentEvents.length}</p>\n <p><strong>Session:</strong> ${t.sessionId}</p>\n ${t.pmCall?`<p><strong>PM Call:</strong> Task delegation to ${t.agentName}</p>`:"<p><strong>Note:</strong> Implied delegation (no explicit PM call found)</p>"}\n </div>\n `;console.log("Agent instance details HTML:",n)}}export{e as E,t as a};
|
|
2
|
+
//# sourceMappingURL=event-viewer.js.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const t=window.io;class e{constructor(){this.socket=null,this.port=null,this.connectionCallbacks={connect:[],disconnect:[],error:[],event:[]},this.isConnected=!1,this.isConnecting=!1,this.events=[],this.sessions=new Map,this.currentSessionId=null,this.startStatusCheckFallback()}connect(t="8765"){this.port=t;const e=`http://localhost:${t}`;if(this.socket&&(this.socket.connected||this.socket.connecting))return console.log("Already connected or connecting, disconnecting first..."),this.socket.disconnect(),void setTimeout(()=>this.doConnect(e),100);this.doConnect(e)}doConnect(e){if(console.log(`Connecting to Socket.IO server at ${e}`),void 0===t)return console.error("Socket.IO library not loaded! Make sure socket.io.min.js is loaded before this script."),void this.notifyConnectionStatus("Socket.IO library not loaded","error");this.isConnecting=!0,this.notifyConnectionStatus("Connecting...","connecting"),this.socket=t(e,{autoConnect:!0,reconnection:!0,reconnectionDelay:1e3,reconnectionDelayMax:1e4,maxReconnectionAttempts:10,timeout:1e4,forceNew:!0,transports:["websocket","polling"]}),this.setupSocketHandlers()}setupSocketHandlers(){this.socket.on("connect",()=>{console.log("Connected to Socket.IO server"),this.isConnected=!0,this.isConnecting=!1,this.notifyConnectionStatus("Connected","connected"),this.connectionCallbacks.connect.forEach(t=>t(this.socket.id)),this.requestStatus()}),this.socket.on("disconnect",t=>{console.log("Disconnected from server:",t),this.isConnected=!1,this.isConnecting=!1,this.notifyConnectionStatus(`Disconnected: ${t}`,"disconnected"),this.connectionCallbacks.disconnect.forEach(e=>e(t))}),this.socket.on("connect_error",t=>{console.error("Connection error:",t),this.isConnecting=!1;const e=t.message||t.description||"Unknown error";this.notifyConnectionStatus(`Connection Error: ${e}`,"disconnected"),this.addEvent({type:"connection.error",timestamp:(new Date).toISOString(),data:{error:e,url:this.socket.io.uri}}),this.connectionCallbacks.error.forEach(t=>t(e))}),this.socket.on("claude_event",t=>{const e=this.transformEvent(t);this.addEvent(e)}),this.socket.on("session.started",t=>{this.addEvent({type:"session",subtype:"started",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("session.ended",t=>{this.addEvent({type:"session",subtype:"ended",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.request",t=>{this.addEvent({type:"claude",subtype:"request",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("claude.response",t=>{this.addEvent({type:"claude",subtype:"response",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.loaded",t=>{this.addEvent({type:"agent",subtype:"loaded",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("agent.executed",t=>{this.addEvent({type:"agent",subtype:"executed",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.pre",t=>{this.addEvent({type:"hook",subtype:"pre",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("hook.post",t=>{this.addEvent({type:"hook",subtype:"post",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("todo.updated",t=>{this.addEvent({type:"todo",subtype:"updated",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("memory.operation",t=>{this.addEvent({type:"memory",subtype:"operation",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("log.entry",t=>{this.addEvent({type:"log",subtype:"entry",timestamp:(new Date).toISOString(),data:t})}),this.socket.on("history",t=>{console.log("Received event history:",t),t&&Array.isArray(t.events)?(console.log(`Processing ${t.events.length} historical events (${t.count} sent, ${t.total_available} total available)`),t.events.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate(),console.log(`Event history loaded: ${t.events.length} events added to dashboard`)):Array.isArray(t)&&(console.log("Received legacy event history format:",t.length,"events"),t.forEach(t=>{const e=this.transformEvent(t);this.addEvent(e,!1)}),this.notifyEventUpdate())}),this.socket.on("system.status",t=>{console.log("Received system status:",t),t.sessions&&this.updateSessions(t.sessions),t.current_session&&(this.currentSessionId=t.current_session)})}disconnect(){this.socket&&(this.socket.disconnect(),this.socket=null),this.port=null,this.isConnected=!1,this.isConnecting=!1}requestStatus(){this.socket&&this.socket.connected&&(console.log("Requesting server status..."),this.socket.emit("request.status"))}requestHistory(t={}){if(this.socket&&this.socket.connected){const e={limit:t.limit||50,event_types:t.event_types||[]};console.log("Requesting event history...",e),this.socket.emit("get_history",e)}else console.warn("Cannot request history: not connected to server")}addEvent(t,e=!0){if(t.timestamp||(t.timestamp=(new Date).toISOString()),t.id||(t.id=Date.now()+Math.random()),this.events.push(t),t.data&&t.data.session_id){const e=t.data.session_id;this.sessions.has(e)||this.sessions.set(e,{id:e,startTime:t.timestamp,lastActivity:t.timestamp,eventCount:0});const n=this.sessions.get(e);n.lastActivity=t.timestamp,n.eventCount++}e&&this.notifyEventUpdate()}updateSessions(t){Array.isArray(t)&&t.forEach(t=>{this.sessions.set(t.id,t)})}clearEvents(){this.events=[],this.sessions.clear(),this.notifyEventUpdate()}refreshHistory(t={}){this.clearEvents(),this.requestHistory(t)}getEventsBySession(t=null){return t?this.events.filter(e=>e.data&&e.data.session_id===t):this.events}onConnection(t,e){this.connectionCallbacks[t]&&this.connectionCallbacks[t].push(e)}onEventUpdate(t){this.connectionCallbacks.event.push(t)}notifyConnectionStatus(t,e){console.log(`SocketClient: Connection status changed to '${t}' (${e})`),this.updateConnectionStatusDOM(t,e),document.dispatchEvent(new CustomEvent("socketConnectionStatus",{detail:{status:t,type:e}}))}updateConnectionStatusDOM(t,e){const n=document.getElementById("connection-status");n?(n.innerHTML=`<span>●</span> ${t}`,n.className=`status-badge status-${e}`,console.log(`SocketClient: Direct DOM update - status: '${t}' (${e})`)):console.warn("SocketClient: Could not find connection-status element in DOM")}notifyEventUpdate(){this.connectionCallbacks.event.forEach(t=>t(this.events,this.sessions)),document.dispatchEvent(new CustomEvent("socketEventUpdate",{detail:{events:this.events,sessions:this.sessions}}))}getConnectionState(){return{isConnected:this.isConnected,isConnecting:this.isConnecting,socketId:this.socket?this.socket.id:null}}transformEvent(t){if(!t)return t;let e={...t};if(!t.type&&t.event){const n=t.event;"TestStart"===n||"TestEnd"===n?(e.type="test",e.subtype=n.toLowerCase().replace("test","")):"SubagentStart"===n||"SubagentStop"===n?(e.type="subagent",e.subtype=n.toLowerCase().replace("subagent","")):"ToolCall"===n?(e.type="tool",e.subtype="call"):"UserPrompt"===n?(e.type="hook",e.subtype="user_prompt"):(e.type="unknown",e.subtype=n.toLowerCase(),e.type===e.subtype&&(e.subtype="event")),delete e.event}else if(t.type){const n=t.type;if(n.startsWith("hook.")){const t=n.substring(5);e.type="hook",e.subtype=t}else if(n.includes(".")){const[t,...s]=n.split(".");e.type=t,e.subtype=s.join(".")}}else e.type="unknown",e.subtype="";if(!t.type&&t.event?e.originalEventName=t.event:t.type&&(e.originalEventName=t.type),t.data&&"object"==typeof t.data){const n=["type","subtype","timestamp","id","event","event_type","originalEventName"];Object.keys(t.data).forEach(s=>{n.includes(s)?console.warn(`Protected field '${s}' in data object was not copied to top level to preserve event structure`):e[s]=t.data[s]}),e.data=t.data}return"hook"!==e.type||"pre_tool"!==e.subtype&&"post_tool"!==e.subtype||console.log("Transformed tool event:",{type:e.type,subtype:e.subtype,tool_name:e.tool_name,has_data:!!e.data,keys:Object.keys(e).filter(t=>"data"!==t)}),e}getState(){return{events:this.events,sessions:this.sessions,currentSessionId:this.currentSessionId}}startStatusCheckFallback(){setInterval(()=>{this.checkAndUpdateStatus()},2e3),"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{setTimeout(()=>this.checkAndUpdateStatus(),100)}):setTimeout(()=>this.checkAndUpdateStatus(),100)}checkAndUpdateStatus(){let t="Disconnected",e="disconnected";this.socket&&(this.socket.connected?(t="Connected",e="connected",this.isConnected=!0,this.isConnecting=!1):this.socket.connecting||this.isConnecting?(t="Connecting...",e="connecting",this.isConnected=!1):(t="Disconnected",e="disconnected",this.isConnected=!1,this.isConnecting=!1));const n=document.getElementById("connection-status");if(n){const s=n.textContent.replace("●","").trim(),o=n.className,i=`status-badge status-${e}`;s===t&&o===i||(console.log(`SocketClient: Fallback update - was '${s}' (${o}), now '${t}' (${i})`),this.updateConnectionStatusDOM(t,e))}}}window.SocketClient=e;class n{constructor(){this.socketClient=null,this.connectionCallbacks=new Set,this.eventUpdateCallbacks=new Set,this.socketClient=new e,window.socketClient=this.socketClient,this.setupSocketEventHandlers(),setTimeout(()=>{this.updateInitialConnectionStatus()},100),console.log("Socket manager initialized")}setupSocketEventHandlers(){document.addEventListener("socketConnectionStatus",t=>{console.log(`SocketManager: Processing connection status update: ${t.detail.status} (${t.detail.type})`),this.handleConnectionStatusChange(t.detail.status,t.detail.type),this.connectionCallbacks.forEach(e=>{try{e(t.detail.status,t.detail.type)}catch(n){console.error("Error in connection callback:",n)}})}),this.socketClient&&this.socketClient.onEventUpdate(t=>{this.eventUpdateCallbacks.forEach(e=>{try{e(t)}catch(n){console.error("Error in event update callback:",n)}})})}handleConnectionStatusChange(t,e){this.updateConnectionStatus(t,e),"connected"===e&&this.socketClient&&this.socketClient.socket&&this.setupGitBranchListener()}updateInitialConnectionStatus(){console.log("SocketManager: Updating initial connection status"),this.socketClient&&"function"==typeof this.socketClient.checkAndUpdateStatus?(console.log("SocketManager: Using socket client checkAndUpdateStatus method"),this.socketClient.checkAndUpdateStatus()):this.socketClient&&this.socketClient.socket?(console.log("SocketManager: Checking socket state directly",{connected:this.socketClient.socket.connected,connecting:this.socketClient.socket.connecting,isConnecting:this.socketClient.isConnecting,isConnected:this.socketClient.isConnected}),this.socketClient.socket.connected?(console.log("SocketManager: Socket is already connected, updating status"),this.updateConnectionStatus("Connected","connected")):this.socketClient.isConnecting||this.socketClient.socket.connecting?(console.log("SocketManager: Socket is connecting, updating status"),this.updateConnectionStatus("Connecting...","connecting")):(console.log("SocketManager: Socket is disconnected, updating status"),this.updateConnectionStatus("Disconnected","disconnected"))):(console.log("SocketManager: No socket client or socket found, setting disconnected status"),this.updateConnectionStatus("Disconnected","disconnected")),setTimeout(()=>{console.log("SocketManager: Secondary status check after 1 second"),this.socketClient&&this.socketClient.socket&&this.socketClient.socket.connected&&(console.log("SocketManager: Socket connected in secondary check, updating status"),this.updateConnectionStatus("Connected","connected"))},1e3)}setupGitBranchListener(){this.socketClient.socket.off("git_branch_response"),this.socketClient.socket.on("git_branch_response",t=>{if(t.success){const e=document.getElementById("footer-git-branch");e&&(e.textContent=t.branch||"unknown"),e&&(e.style.display="inline")}else console.error("Git branch request failed:",t.error)})}updateConnectionStatus(t,e){const n=document.getElementById("connection-status");if(n){if(n.querySelector("span")){const e="●";n.innerHTML=`<span>${e}</span> ${t}`}else n.textContent=t;n.className=`status-badge status-${e}`,console.log(`SocketManager: UI updated - status: '${t}' (${e})`)}else console.error("SocketManager: Could not find connection-status element in DOM")}connect(t){this.socketClient&&this.socketClient.connect(t)}disconnect(){this.socketClient&&this.socketClient.disconnect()}isConnected(){return this.socketClient&&this.socketClient.isConnected}isConnecting(){return this.socketClient&&this.socketClient.isConnecting}getSocketClient(){return this.socketClient}getSocket(){return this.socketClient?this.socketClient.socket:null}onConnectionStatusChange(t){this.connectionCallbacks.add(t)}offConnectionStatusChange(t){this.connectionCallbacks.delete(t)}onEventUpdate(t){this.eventUpdateCallbacks.add(t)}offEventUpdate(t){this.eventUpdateCallbacks.delete(t)}toggleConnectionControls(){const t=document.getElementById("connection-controls-row"),e=document.getElementById("connection-toggle-btn");if(t&&e){t.classList.contains("show")?(t.classList.remove("show"),t.style.display="none",e.textContent="Connection Settings"):(t.classList.add("show"),t.style.display="block",e.textContent="Hide Settings")}}setupConnectionControls(){const t=document.getElementById("connect-btn"),e=document.getElementById("disconnect-btn"),n=document.getElementById("connection-toggle-btn");t&&t.addEventListener("click",()=>{const t=document.getElementById("port-input").value||8765;this.connect(t)}),e&&e.addEventListener("click",()=>{this.disconnect()}),n&&n.addEventListener("click",()=>{this.toggleConnectionControls()})}initializeFromURL(t){const e=t.get("port"),n=document.getElementById("port-input");let s=e;s||"http:"!==window.location.protocol||(s=window.location.port||"8765"),s||(s=n?.value||"8765"),n&&(n.value=s);!("false"!==t.get("connect"))||this.isConnected()||this.isConnecting()||this.connect(s)}}class s{constructor(){this.currentTab="events",this.autoScroll=!0,this.selectedCard={tab:null,index:null,type:null,data:null},this.tabNavigation={events:{selectedIndex:-1,items:[]},agents:{selectedIndex:-1,items:[]},tools:{selectedIndex:-1,items:[]},files:{selectedIndex:-1,items:[]}},this.setupEventHandlers(),console.log("UI state manager initialized")}setupEventHandlers(){this.setupTabNavigation(),this.setupUnifiedKeyboardNavigation()}setupTabNavigation(){document.querySelectorAll(".tab-button").forEach(t=>{t.addEventListener("click",()=>{const e=this.getTabNameFromButton(t);this.switchTab(e)})})}setupUnifiedKeyboardNavigation(){document.addEventListener("keydown",t=>{document.activeElement&&["INPUT","TEXTAREA","SELECT"].includes(document.activeElement.tagName)||("ArrowUp"===t.key||"ArrowDown"===t.key?(t.preventDefault(),this.handleUnifiedArrowNavigation("ArrowDown"===t.key?1:-1)):"Enter"===t.key?(t.preventDefault(),this.handleUnifiedEnterKey()):"Escape"===t.key&&this.clearUnifiedSelection())})}getTabNameFromButton(t){const e=t.textContent.toLowerCase();return e.includes("events")?"events":e.includes("agents")?"agents":e.includes("tools")?"tools":e.includes("files")?"files":"events"}switchTab(t){console.log(`[DEBUG] switchTab called with tabName: ${t}`);const e=this.currentTab;this.currentTab=t,document.querySelectorAll(".tab-button").forEach(e=>{e.classList.remove("active"),this.getTabNameFromButton(e)===t&&e.classList.add("active")}),document.querySelectorAll(".tab-content").forEach(t=>{t.classList.remove("active")});const n=document.getElementById(`${t}-tab`);n&&n.classList.add("active"),this.clearUnifiedSelection(),document.dispatchEvent(new CustomEvent("tabChanged",{detail:{newTab:t,previousTab:e}})),setTimeout(()=>{this.autoScroll&&this.scrollCurrentTabToBottom()},100)}handleUnifiedArrowNavigation(t){const e=this.tabNavigation[this.currentTab];if(!e)return;let n=e.selectedIndex+t;0!==e.items.length&&(n<0?n=e.items.length-1:n>=e.items.length&&(n=0),this.selectCardByIndex(this.currentTab,n))}handleUnifiedEnterKey(){const t=this.tabNavigation[this.currentTab];if(!t||-1===t.selectedIndex)return;const e=t.items[t.selectedIndex];e&&e.onclick&&e.onclick()}clearUnifiedSelection(){Object.keys(this.tabNavigation).forEach(t=>{this.tabNavigation[t].selectedIndex=-1}),this.clearCardSelection()}updateTabNavigationItems(){const t=this.tabNavigation[this.currentTab];if(!t)return;let e;switch(this.currentTab){case"events":e="#events-list .event-item";break;case"agents":e="#agents-list .event-item";break;case"tools":e="#tools-list .event-item";break;case"files":e="#files-list .event-item"}e&&(t.items=Array.from(document.querySelectorAll(e)))}selectCardByIndex(t,e){const n=this.tabNavigation[t];if(!n||e<0||e>=n.items.length)return;n.selectedIndex=e,this.updateUnifiedSelectionUI();n.items[e]&&this.selectCard(t,e,this.getCardType(t),e),this.showCardDetails(t,e)}updateUnifiedSelectionUI(){document.querySelectorAll(".event-item.keyboard-selected").forEach(t=>{t.classList.remove("keyboard-selected")});const t=this.tabNavigation[this.currentTab];t&&-1!==t.selectedIndex&&t.items[t.selectedIndex]&&t.items[t.selectedIndex].classList.add("keyboard-selected")}showCardDetails(t,e){document.dispatchEvent(new CustomEvent("showCardDetails",{detail:{tabName:t,index:e}}))}selectCard(t,e,n,s){this.clearCardSelection(),this.selectedCard={tab:t,index:e,type:n,data:s},this.updateCardSelectionUI(),console.log("Card selected:",this.selectedCard)}clearCardSelection(){document.querySelectorAll(".event-item.selected, .file-item.selected").forEach(t=>{t.classList.remove("selected")}),this.selectedCard={tab:null,index:null,type:null,data:null}}updateCardSelectionUI(){if(!this.selectedCard.tab||null===this.selectedCard.index)return;let t;switch(this.selectedCard.tab){case"events":t=document.getElementById("events-list");break;case"agents":t=document.getElementById("agents-list");break;case"tools":t=document.getElementById("tools-list");break;case"files":t=document.getElementById("files-list")}if(t){const e=t.querySelectorAll(".event-item, .file-item");e[this.selectedCard.index]&&e[this.selectedCard.index].classList.add("selected")}}getCardType(t){switch(t){case"events":return"event";case"agents":return"agent";case"tools":return"tool";case"files":return"file";default:return"unknown"}}scrollCurrentTabToBottom(){const t=`${this.currentTab}-list`,e=document.getElementById(t);e&&this.autoScroll&&(e.scrollTop=e.scrollHeight)}clearSelection(){this.clearCardSelection(),this.clearUnifiedSelection()}getCurrentTab(){return this.currentTab}getSelectedCard(){return{...this.selectedCard}}getTabNavigation(){return{...this.tabNavigation}}setAutoScroll(t){this.autoScroll=t}getAutoScroll(){return this.autoScroll}}export{n as S,s as U};
|
|
2
|
+
//# sourceMappingURL=socket-client.js.map
|
{claude_mpm-4.0.4 → claude_mpm-4.0.9}/src/claude_mpm/dashboard/static/js/components/event-viewer.js
RENAMED
|
@@ -282,6 +282,10 @@ class EventViewer {
|
|
|
282
282
|
formatEventType(event) {
|
|
283
283
|
// If we have type and subtype, use them
|
|
284
284
|
if (event.type && event.subtype) {
|
|
285
|
+
// Check if type and subtype are identical to prevent "type.type" display
|
|
286
|
+
if (event.type === event.subtype) {
|
|
287
|
+
return event.type;
|
|
288
|
+
}
|
|
285
289
|
return `${event.type}.${event.subtype}`;
|
|
286
290
|
}
|
|
287
291
|
// If we have just type, use it
|
|
@@ -464,8 +464,14 @@ class SocketClient {
|
|
|
464
464
|
transformedEvent.subtype = 'user_prompt';
|
|
465
465
|
} else {
|
|
466
466
|
// Generic fallback for unknown event names
|
|
467
|
-
|
|
467
|
+
// Use 'unknown' for type and the actual eventName for subtype
|
|
468
|
+
transformedEvent.type = 'unknown';
|
|
468
469
|
transformedEvent.subtype = eventName.toLowerCase();
|
|
470
|
+
|
|
471
|
+
// Prevent duplicate type/subtype values
|
|
472
|
+
if (transformedEvent.type === transformedEvent.subtype) {
|
|
473
|
+
transformedEvent.subtype = 'event';
|
|
474
|
+
}
|
|
469
475
|
}
|
|
470
476
|
|
|
471
477
|
// Remove the 'event' field to avoid confusion
|
|
@@ -70,30 +70,78 @@ class SocketIOConnectionPool:
|
|
|
70
70
|
return None
|
|
71
71
|
|
|
72
72
|
def _create_connection(self, port: int) -> Optional[Any]:
|
|
73
|
-
"""Create a new Socket.IO connection.
|
|
73
|
+
"""Create a new Socket.IO connection with persistent keep-alive.
|
|
74
|
+
|
|
75
|
+
WHY persistent connections:
|
|
76
|
+
- Maintains connection throughout handler lifecycle
|
|
77
|
+
- Automatic reconnection on disconnect
|
|
78
|
+
- Reduced connection overhead for multiple events
|
|
79
|
+
- Better reliability for event delivery
|
|
80
|
+
"""
|
|
74
81
|
if not SOCKETIO_AVAILABLE:
|
|
75
82
|
return None
|
|
76
83
|
try:
|
|
77
84
|
client = socketio.Client(
|
|
78
|
-
reconnection=
|
|
85
|
+
reconnection=True, # Enable automatic reconnection
|
|
86
|
+
reconnection_attempts=5, # Try to reconnect up to 5 times
|
|
87
|
+
reconnection_delay=0.5, # Wait 0.5s between reconnection attempts
|
|
88
|
+
reconnection_delay_max=2.0, # Max delay between attempts
|
|
79
89
|
logger=False,
|
|
80
|
-
engineio_logger=False,
|
|
90
|
+
engineio_logger=False,
|
|
81
91
|
)
|
|
92
|
+
|
|
93
|
+
# Set up event handlers for connection lifecycle
|
|
94
|
+
@client.on('connect')
|
|
95
|
+
def on_connect():
|
|
96
|
+
pass # Connection established
|
|
97
|
+
|
|
98
|
+
@client.on('disconnect')
|
|
99
|
+
def on_disconnect():
|
|
100
|
+
pass # Will automatically try to reconnect
|
|
101
|
+
|
|
82
102
|
client.connect(
|
|
83
103
|
f"http://localhost:{port}",
|
|
84
|
-
wait=True,
|
|
104
|
+
wait=True, # Wait for connection to establish
|
|
85
105
|
wait_timeout=NetworkConfig.SOCKET_WAIT_TIMEOUT,
|
|
106
|
+
transports=['websocket', 'polling'], # Try WebSocket first, fall back to polling
|
|
86
107
|
)
|
|
108
|
+
|
|
87
109
|
if client.connected:
|
|
110
|
+
# Send a keep-alive ping to establish the connection
|
|
111
|
+
try:
|
|
112
|
+
client.emit('ping', {'timestamp': time.time()})
|
|
113
|
+
except:
|
|
114
|
+
pass # Ignore ping errors
|
|
88
115
|
return client
|
|
89
116
|
except Exception:
|
|
90
117
|
pass
|
|
91
118
|
return None
|
|
92
119
|
|
|
93
120
|
def _is_connection_alive(self, client: Any) -> bool:
|
|
94
|
-
"""Check if a connection is still alive.
|
|
121
|
+
"""Check if a connection is still alive.
|
|
122
|
+
|
|
123
|
+
WHY enhanced check:
|
|
124
|
+
- Verifies actual connection state
|
|
125
|
+
- Attempts to ping server for liveness check
|
|
126
|
+
- More reliable than just checking connected flag
|
|
127
|
+
"""
|
|
95
128
|
try:
|
|
96
|
-
|
|
129
|
+
if not client:
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
# Check basic connection state
|
|
133
|
+
if not client.connected:
|
|
134
|
+
return False
|
|
135
|
+
|
|
136
|
+
# Try a quick ping to verify connection is truly alive
|
|
137
|
+
# This helps detect zombie connections
|
|
138
|
+
try:
|
|
139
|
+
# Just emit a ping, don't wait for response (faster)
|
|
140
|
+
client.emit('ping', {'timestamp': time.time()})
|
|
141
|
+
return True
|
|
142
|
+
except:
|
|
143
|
+
# If ping fails, connection might be dead
|
|
144
|
+
return client.connected # Fall back to basic check
|
|
97
145
|
except:
|
|
98
146
|
return False
|
|
99
147
|
|
|
@@ -106,12 +154,27 @@ class SocketIOConnectionPool:
|
|
|
106
154
|
pass
|
|
107
155
|
|
|
108
156
|
def _cleanup_dead_connections(self) -> None:
|
|
109
|
-
"""Remove dead connections from the pool.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
157
|
+
"""Remove dead connections from the pool and attempt reconnection.
|
|
158
|
+
|
|
159
|
+
WHY proactive reconnection:
|
|
160
|
+
- Maintains pool health
|
|
161
|
+
- Ensures connections are ready when needed
|
|
162
|
+
- Reduces latency for event emission
|
|
163
|
+
"""
|
|
164
|
+
alive_connections = []
|
|
165
|
+
for conn in self.connections:
|
|
166
|
+
client = conn.get("client")
|
|
167
|
+
if self._is_connection_alive(client):
|
|
168
|
+
alive_connections.append(conn)
|
|
169
|
+
else:
|
|
170
|
+
# Try to reconnect dead connections
|
|
171
|
+
self._close_connection(client)
|
|
172
|
+
new_client = self._create_connection(conn.get("port", 8765))
|
|
173
|
+
if new_client:
|
|
174
|
+
conn["client"] = new_client
|
|
175
|
+
conn["created"] = time.time()
|
|
176
|
+
alive_connections.append(conn)
|
|
177
|
+
self.connections = alive_connections
|
|
115
178
|
|
|
116
179
|
def close_all(self) -> None:
|
|
117
180
|
"""Close all connections in the pool."""
|
|
@@ -17,6 +17,7 @@ import json
|
|
|
17
17
|
import os
|
|
18
18
|
import select
|
|
19
19
|
import signal
|
|
20
|
+
import subprocess
|
|
20
21
|
import sys
|
|
21
22
|
import threading
|
|
22
23
|
import time
|
|
@@ -434,12 +435,13 @@ class ClaudeHookHandler:
|
|
|
434
435
|
return int(os.environ.get("CLAUDE_MPM_SOCKETIO_PORT", "8765"))
|
|
435
436
|
|
|
436
437
|
def _emit_socketio_event(self, namespace: str, event: str, data: dict):
|
|
437
|
-
"""Emit Socket.IO event with improved reliability and
|
|
438
|
+
"""Emit Socket.IO event with improved reliability and persistent connections.
|
|
438
439
|
|
|
439
440
|
WHY improved approach:
|
|
440
|
-
-
|
|
441
|
-
-
|
|
442
|
-
-
|
|
441
|
+
- Maintains persistent connections throughout handler lifecycle
|
|
442
|
+
- Better error handling and automatic recovery
|
|
443
|
+
- Connection health monitoring before emission
|
|
444
|
+
- Automatic reconnection for critical events
|
|
443
445
|
- Validates data before emission
|
|
444
446
|
"""
|
|
445
447
|
# Always try to emit Socket.IO events if available
|
|
@@ -448,15 +450,56 @@ class ClaudeHookHandler:
|
|
|
448
450
|
# Get Socket.IO client with dynamic port discovery
|
|
449
451
|
port = self._discover_socketio_port()
|
|
450
452
|
client = self.connection_pool.get_connection(port)
|
|
453
|
+
|
|
454
|
+
# If no client available, try to create one
|
|
451
455
|
if not client:
|
|
452
456
|
if DEBUG:
|
|
453
457
|
print(
|
|
454
|
-
f"Hook handler: No Socket.IO client available for event: hook.{event}",
|
|
458
|
+
f"Hook handler: No Socket.IO client available, attempting to create connection for event: hook.{event}",
|
|
455
459
|
file=sys.stderr,
|
|
456
460
|
)
|
|
457
|
-
|
|
461
|
+
# Force creation of a new connection
|
|
462
|
+
client = self.connection_pool._create_connection(port)
|
|
463
|
+
if client:
|
|
464
|
+
# Add to pool for future use
|
|
465
|
+
self.connection_pool.connections.append(
|
|
466
|
+
{"port": port, "client": client, "created": time.time()}
|
|
467
|
+
)
|
|
468
|
+
else:
|
|
469
|
+
if DEBUG:
|
|
470
|
+
print(
|
|
471
|
+
f"Hook handler: Failed to create Socket.IO connection for event: hook.{event}",
|
|
472
|
+
file=sys.stderr,
|
|
473
|
+
)
|
|
474
|
+
return
|
|
458
475
|
|
|
459
476
|
try:
|
|
477
|
+
# Verify connection is alive before emitting
|
|
478
|
+
if not client.connected:
|
|
479
|
+
if DEBUG:
|
|
480
|
+
print(
|
|
481
|
+
f"Hook handler: Client not connected, attempting reconnection for event: hook.{event}",
|
|
482
|
+
file=sys.stderr,
|
|
483
|
+
)
|
|
484
|
+
# Try to reconnect
|
|
485
|
+
try:
|
|
486
|
+
client.connect(
|
|
487
|
+
f"http://localhost:{port}",
|
|
488
|
+
wait=True,
|
|
489
|
+
wait_timeout=1.0,
|
|
490
|
+
transports=['websocket', 'polling'],
|
|
491
|
+
)
|
|
492
|
+
except:
|
|
493
|
+
# If reconnection fails, get a fresh client
|
|
494
|
+
client = self.connection_pool._create_connection(port)
|
|
495
|
+
if not client:
|
|
496
|
+
if DEBUG:
|
|
497
|
+
print(
|
|
498
|
+
f"Hook handler: Reconnection failed for event: hook.{event}",
|
|
499
|
+
file=sys.stderr,
|
|
500
|
+
)
|
|
501
|
+
return
|
|
502
|
+
|
|
460
503
|
# Format event for Socket.IO server
|
|
461
504
|
claude_event_data = {
|
|
462
505
|
"type": f"hook.{event}", # Dashboard expects 'hook.' prefix
|
|
@@ -480,19 +523,23 @@ class ClaudeHookHandler:
|
|
|
480
523
|
file=sys.stderr,
|
|
481
524
|
)
|
|
482
525
|
|
|
483
|
-
# Emit synchronously
|
|
526
|
+
# Emit synchronously
|
|
484
527
|
client.emit("claude_event", claude_event_data)
|
|
528
|
+
|
|
529
|
+
# For critical events, wait a moment to ensure delivery
|
|
530
|
+
if event in ["subagent_stop", "pre_tool"]:
|
|
531
|
+
time.sleep(0.01) # Small delay to ensure event is sent
|
|
485
532
|
|
|
486
533
|
# Verify emission for critical events
|
|
487
534
|
if event in ["subagent_stop", "pre_tool"] and DEBUG:
|
|
488
535
|
if client.connected:
|
|
489
536
|
print(
|
|
490
|
-
f"✅ Successfully emitted Socket.IO event: hook.{event}",
|
|
537
|
+
f"✅ Successfully emitted Socket.IO event: hook.{event} (connection still active)",
|
|
491
538
|
file=sys.stderr,
|
|
492
539
|
)
|
|
493
540
|
else:
|
|
494
541
|
print(
|
|
495
|
-
f"⚠️ Event emitted but connection
|
|
542
|
+
f"⚠️ Event emitted but connection closed after: hook.{event}",
|
|
496
543
|
file=sys.stderr,
|
|
497
544
|
)
|
|
498
545
|
|
|
@@ -507,12 +554,16 @@ class ClaudeHookHandler:
|
|
|
507
554
|
f"Hook handler: Attempting immediate reconnection for critical event: hook.{event}",
|
|
508
555
|
file=sys.stderr,
|
|
509
556
|
)
|
|
510
|
-
#
|
|
511
|
-
|
|
512
|
-
retry_client = self.connection_pool.
|
|
557
|
+
# Force get a new client and emit again
|
|
558
|
+
self.connection_pool._cleanup_dead_connections()
|
|
559
|
+
retry_client = self.connection_pool._create_connection(port)
|
|
513
560
|
if retry_client:
|
|
514
561
|
try:
|
|
515
562
|
retry_client.emit("claude_event", claude_event_data)
|
|
563
|
+
# Add to pool for future use
|
|
564
|
+
self.connection_pool.connections.append(
|
|
565
|
+
{"port": port, "client": retry_client, "created": time.time()}
|
|
566
|
+
)
|
|
516
567
|
if DEBUG:
|
|
517
568
|
print(
|
|
518
569
|
f"✅ Successfully re-emitted event after reconnection: hook.{event}",
|