claude-mpm 4.0.4__tar.gz → 4.0.8__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.
Files changed (433) hide show
  1. {claude_mpm-4.0.4/src/claude_mpm.egg-info → claude_mpm-4.0.8}/PKG-INFO +1 -1
  2. claude_mpm-4.0.8/VERSION +1 -0
  3. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/pyproject.toml +1 -1
  4. claude_mpm-4.0.8/src/claude_mpm/VERSION +1 -0
  5. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/constants.py +4 -1
  6. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/framework_loader.py +102 -14
  7. claude_mpm-4.0.8/src/claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  8. claude_mpm-4.0.8/src/claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  9. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/event-viewer.js +4 -0
  10. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/socket-client.js +7 -1
  11. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/connection_pool.py +75 -12
  12. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/hook_handler.py +63 -12
  13. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/system_instructions_service.py +22 -7
  14. {claude_mpm-4.0.4 → claude_mpm-4.0.8/src/claude_mpm.egg-info}/PKG-INFO +1 -1
  15. claude_mpm-4.0.4/VERSION +0 -1
  16. claude_mpm-4.0.4/src/claude_mpm/VERSION +0 -1
  17. claude_mpm-4.0.4/src/claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  18. claude_mpm-4.0.4/src/claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  19. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/CLAUDE.md +0 -0
  20. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/LICENSE +0 -0
  21. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/MANIFEST.in +0 -0
  22. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/README.md +0 -0
  23. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/claude-mpm +0 -0
  24. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/requirements.txt +0 -0
  25. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/scripts/ticket +0 -0
  26. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/setup.cfg +0 -0
  27. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/setup.py +0 -0
  28. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/__init__.py +0 -0
  29. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/__main__.py +0 -0
  30. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -0
  31. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/BASE_PM.md +0 -0
  32. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/INSTRUCTIONS.md +0 -0
  33. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/MEMORY.md +0 -0
  34. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/WORKFLOW.md +0 -0
  35. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/__init__.py +0 -0
  36. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/agent_loader.py +0 -0
  37. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/agent_loader_integration.py +0 -0
  38. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/agents_metadata.py +0 -0
  39. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/async_agent_loader.py +0 -0
  40. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/backups/INSTRUCTIONS.md +0 -0
  41. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/base_agent.json +0 -0
  42. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/base_agent_loader.py +0 -0
  43. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/frontmatter_validator.py +0 -0
  44. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/schema/agent_schema.json +0 -0
  45. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/system_agent_config.py +0 -0
  46. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/__init__.py +0 -0
  47. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -0
  48. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -0
  49. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -0
  50. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -0
  51. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -0
  52. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/research_agent_2025011_234551.json +0 -0
  53. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -0
  54. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/research_memory_efficient.json +0 -0
  55. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -0
  56. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -0
  57. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/code_analyzer.json +0 -0
  58. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/data_engineer.json +0 -0
  59. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/documentation.json +0 -0
  60. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/engineer.json +0 -0
  61. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/memory_manager.json +0 -0
  62. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/ops.json +0 -0
  63. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/project_organizer.json +0 -0
  64. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/qa.json +0 -0
  65. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/refactoring_engineer.json +0 -0
  66. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/research.json +0 -0
  67. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/security.json +0 -0
  68. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/ticketing.json +0 -0
  69. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/version_control.json +0 -0
  70. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/web_qa.json +0 -0
  71. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/agents/templates/web_ui.json +0 -0
  72. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/__init__.py +0 -0
  73. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/__main__.py +0 -0
  74. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/__init__.py +0 -0
  75. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/agents.py +0 -0
  76. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/aggregate.py +0 -0
  77. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/cleanup.py +0 -0
  78. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/config.py +0 -0
  79. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/info.py +0 -0
  80. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp.py +0 -0
  81. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp_command_router.py +0 -0
  82. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp_config_commands.py +0 -0
  83. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp_install_commands.py +0 -0
  84. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp_server_commands.py +0 -0
  85. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/mcp_tool_commands.py +0 -0
  86. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/memory.py +0 -0
  87. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/monitor.py +0 -0
  88. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/run.py +0 -0
  89. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/run_config_checker.py +0 -0
  90. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/socketio_monitor.py +0 -0
  91. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/commands/tickets.py +0 -0
  92. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parser.py +0 -0
  93. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/__init__.py +0 -0
  94. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/agents_parser.py +0 -0
  95. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/base_parser.py +0 -0
  96. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/config_parser.py +0 -0
  97. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/mcp_parser.py +0 -0
  98. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/memory_parser.py +0 -0
  99. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/monitor_parser.py +0 -0
  100. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/run_parser.py +0 -0
  101. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/parsers/tickets_parser.py +0 -0
  102. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/ticket_cli.py +0 -0
  103. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli/utils.py +0 -0
  104. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli_module/__init__.py +0 -0
  105. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli_module/args.py +0 -0
  106. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli_module/commands.py +0 -0
  107. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/cli_module/migration_example.py +0 -0
  108. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/config/__init__.py +0 -0
  109. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/config/agent_config.py +0 -0
  110. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/config/experimental_features.py +0 -0
  111. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/config/paths.py +0 -0
  112. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/config/socketio_config.py +0 -0
  113. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/__init__.py +0 -0
  114. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/agent_name_normalizer.py +0 -0
  115. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/agent_registry.py +0 -0
  116. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/agent_session_manager.py +0 -0
  117. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/base_service.py +0 -0
  118. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/cache.py +0 -0
  119. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/claude_runner.py +0 -0
  120. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/config.py +0 -0
  121. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/config_aliases.py +0 -0
  122. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/config_constants.py +0 -0
  123. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/constants.py +0 -0
  124. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/container.py +0 -0
  125. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/exceptions.py +0 -0
  126. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/factories.py +0 -0
  127. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/hook_manager.py +0 -0
  128. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/hook_performance_config.py +0 -0
  129. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/injectable_service.py +0 -0
  130. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/interactive_session.py +0 -0
  131. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/interfaces.py +0 -0
  132. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/lazy.py +0 -0
  133. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/logger.py +0 -0
  134. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/logging_config.py +0 -0
  135. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/minimal_framework_loader.py +0 -0
  136. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/mixins.py +0 -0
  137. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/oneshot_session.py +0 -0
  138. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/optimized_agent_loader.py +0 -0
  139. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/optimized_startup.py +0 -0
  140. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/pm_hook_interceptor.py +0 -0
  141. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/service_registry.py +0 -0
  142. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/session_manager.py +0 -0
  143. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/socketio_pool.py +0 -0
  144. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/tool_access_control.py +0 -0
  145. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/types.py +0 -0
  146. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/typing_utils.py +0 -0
  147. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/unified_agent_registry.py +0 -0
  148. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/unified_config.py +0 -0
  149. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/core/unified_paths.py +0 -0
  150. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/index.html +0 -0
  151. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/open_dashboard.py +0 -0
  152. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/agent-inference.js +0 -0
  153. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/event-processor.js +0 -0
  154. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/event-viewer.js +0 -0
  155. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/export-manager.js +0 -0
  156. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -0
  157. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -0
  158. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/hud-manager.js +0 -0
  159. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -0
  160. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/module-viewer.js +0 -0
  161. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/session-manager.js +0 -0
  162. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/socket-manager.js +0 -0
  163. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -0
  164. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/components/working-directory.js +0 -0
  165. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/dashboard.js +0 -0
  166. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/built/socket-client.js +0 -0
  167. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/css/dashboard.css +0 -0
  168. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -0
  169. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/event-processor.js +0 -0
  170. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/export-manager.js +0 -0
  171. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -0
  172. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -0
  173. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -0
  174. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -0
  175. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -0
  176. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/session-manager.js +0 -0
  177. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -0
  178. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -0
  179. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/components/working-directory.js +0 -0
  180. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/dist/dashboard.js +0 -0
  181. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/agent-inference.js +0 -0
  182. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/event-processor.js +0 -0
  183. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/export-manager.js +0 -0
  184. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -0
  185. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -0
  186. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/hud-manager.js +0 -0
  187. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -0
  188. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/module-viewer.js +0 -0
  189. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/session-manager.js +0 -0
  190. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/socket-manager.js +0 -0
  191. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -0
  192. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/components/working-directory.js +0 -0
  193. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/dashboard.js +0 -0
  194. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/static/js/extension-error-handler.js +0 -0
  195. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/templates/index.html +0 -0
  196. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/dashboard/test_dashboard.html +0 -0
  197. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/experimental/cli_enhancements.py +0 -0
  198. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/generators/__init__.py +0 -0
  199. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/generators/agent_profile_generator.py +0 -0
  200. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/__init__.py +0 -0
  201. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/base_hook.py +0 -0
  202. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/__init__.py +0 -0
  203. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/event_handlers.py +0 -0
  204. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/hook_wrapper.sh +0 -0
  205. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/memory_integration.py +0 -0
  206. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/response_tracking.py +0 -0
  207. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/claude_hooks/tool_analysis.py +0 -0
  208. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/memory_integration_hook.py +0 -0
  209. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/tool_call_interceptor.py +0 -0
  210. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/hooks/validation_hooks.py +0 -0
  211. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/init.py +0 -0
  212. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/models/__init__.py +0 -0
  213. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/models/agent_definition.py +0 -0
  214. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/models/agent_session.py +0 -0
  215. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/scripts/__init__.py +0 -0
  216. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/scripts/socketio_daemon.py +0 -0
  217. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/scripts/socketio_server_manager.py +0 -0
  218. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/scripts/start_activity_logging.py +0 -0
  219. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/__init__.py +0 -0
  220. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agent_capabilities_service.py +0 -0
  221. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/__init__.py +0 -0
  222. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/__init__.py +0 -0
  223. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_config_provider.py +0 -0
  224. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_configuration_manager.py +0 -0
  225. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_definition_factory.py +0 -0
  226. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_deployment.py +0 -0
  227. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_discovery_service.py +0 -0
  228. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_environment_manager.py +0 -0
  229. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_filesystem_manager.py +0 -0
  230. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_format_converter.py +0 -0
  231. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +0 -0
  232. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +0 -0
  233. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_metrics_collector.py +0 -0
  234. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -0
  235. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_template_builder.py +0 -0
  236. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_validator.py +0 -0
  237. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_version_manager.py +0 -0
  238. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agent_versioning.py +0 -0
  239. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/agents_directory_resolver.py +0 -0
  240. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/async_agent_deployment.py +0 -0
  241. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/config/__init__.py +0 -0
  242. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/config/deployment_config.py +0 -0
  243. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/config/deployment_config_manager.py +0 -0
  244. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/deployment_config_loader.py +0 -0
  245. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/deployment_type_detector.py +0 -0
  246. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/facade/__init__.py +0 -0
  247. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +0 -0
  248. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -0
  249. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/facade/deployment_facade.py +0 -0
  250. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +0 -0
  251. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/interface_adapter.py +0 -0
  252. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/lifecycle_health_checker.py +0 -0
  253. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +0 -0
  254. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/__init__.py +0 -0
  255. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +0 -0
  256. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +0 -0
  257. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +0 -0
  258. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +0 -0
  259. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +0 -0
  260. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -0
  261. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +0 -0
  262. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +0 -0
  263. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +0 -0
  264. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/processors/__init__.py +0 -0
  265. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +0 -0
  266. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +0 -0
  267. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/processors/agent_processor.py +0 -0
  268. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +0 -0
  269. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/results/__init__.py +0 -0
  270. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/results/deployment_metrics.py +0 -0
  271. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/results/deployment_result_builder.py +0 -0
  272. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/__init__.py +0 -0
  273. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/base_strategy.py +0 -0
  274. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/project_strategy.py +0 -0
  275. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/strategy_selector.py +0 -0
  276. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/system_strategy.py +0 -0
  277. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/strategies/user_strategy.py +0 -0
  278. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/system_instructions_deployer.py +0 -0
  279. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/validation/__init__.py +0 -0
  280. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/validation/agent_validator.py +0 -0
  281. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/validation/deployment_validator.py +0 -0
  282. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/validation/template_validator.py +0 -0
  283. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/deployment/validation/validation_result.py +0 -0
  284. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/loading/__init__.py +0 -0
  285. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/loading/agent_profile_loader.py +0 -0
  286. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/loading/base_agent_manager.py +0 -0
  287. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/loading/framework_agent_loader.py +0 -0
  288. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/management/__init__.py +0 -0
  289. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/management/agent_capabilities_generator.py +0 -0
  290. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/management/agent_management_service.py +0 -0
  291. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/__init__.py +0 -0
  292. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/agent_memory_manager.py +0 -0
  293. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/agent_persistence_service.py +0 -0
  294. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/analyzer.py +0 -0
  295. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/content_manager.py +0 -0
  296. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/memory/template_generator.py +0 -0
  297. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/registry/__init__.py +0 -0
  298. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/registry/deployed_agent_discovery.py +0 -0
  299. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/agents/registry/modification_tracker.py +0 -0
  300. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/async_session_logger.py +0 -0
  301. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/claude_session_logger.py +0 -0
  302. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/command_handler_service.py +0 -0
  303. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/communication/__init__.py +0 -0
  304. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/__init__.py +0 -0
  305. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/base.py +0 -0
  306. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces/__init__.py +0 -0
  307. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces/agent.py +0 -0
  308. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces/communication.py +0 -0
  309. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces/infrastructure.py +0 -0
  310. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces/service.py +0 -0
  311. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/core/interfaces.py +0 -0
  312. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/event_aggregator.py +0 -0
  313. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/exceptions.py +0 -0
  314. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/__init__.py +0 -0
  315. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/content_assembler.py +0 -0
  316. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/content_validator.py +0 -0
  317. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/deployment_manager.py +0 -0
  318. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -0
  319. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -0
  320. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +0 -0
  321. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +0 -0
  322. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +0 -0
  323. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +0 -0
  324. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +0 -0
  325. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/header.py +0 -0
  326. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +0 -0
  327. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +0 -0
  328. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +0 -0
  329. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +0 -0
  330. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +0 -0
  331. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/section_manager.py +0 -0
  332. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/framework_claude_md_generator/version_manager.py +0 -0
  333. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/hook_service.py +0 -0
  334. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/infrastructure/__init__.py +0 -0
  335. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/infrastructure/context_preservation.py +0 -0
  336. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/infrastructure/daemon_manager.py +0 -0
  337. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/infrastructure/logging.py +0 -0
  338. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/infrastructure/monitoring.py +0 -0
  339. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/__init__.py +0 -0
  340. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/config/__init__.py +0 -0
  341. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/config/config_loader.py +0 -0
  342. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/config/config_schema.py +0 -0
  343. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/config/configuration.py +0 -0
  344. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/core/__init__.py +0 -0
  345. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/core/base.py +0 -0
  346. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/core/exceptions.py +0 -0
  347. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/core/interfaces.py +0 -0
  348. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/main.py +0 -0
  349. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/registry/__init__.py +0 -0
  350. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -0
  351. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -0
  352. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/server/__init__.py +0 -0
  353. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -0
  354. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -0
  355. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -0
  356. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/__init__.py +0 -0
  357. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -0
  358. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -0
  359. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -0
  360. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -0
  361. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -0
  362. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/__init__.py +0 -0
  363. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/builder.py +0 -0
  364. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/cache/__init__.py +0 -0
  365. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/cache/shared_prompt_cache.py +0 -0
  366. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/cache/simple_cache.py +0 -0
  367. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/indexed_memory.py +0 -0
  368. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/optimizer.py +0 -0
  369. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory/router.py +0 -0
  370. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/memory_hook_service.py +0 -0
  371. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/port_manager.py +0 -0
  372. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/project/__init__.py +0 -0
  373. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/project/analyzer.py +0 -0
  374. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/project/registry.py +0 -0
  375. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/recovery_manager.py +0 -0
  376. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/response_tracker.py +0 -0
  377. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/runner_configuration_service.py +0 -0
  378. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/session_management_service.py +0 -0
  379. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/__init__.py +0 -0
  380. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/client_proxy.py +0 -0
  381. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/__init__.py +0 -0
  382. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/base.py +0 -0
  383. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/connection.py +0 -0
  384. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/file.py +0 -0
  385. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/git.py +0 -0
  386. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/hook.py +0 -0
  387. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/memory.py +0 -0
  388. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/project.py +0 -0
  389. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/handlers/registry.py +0 -0
  390. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/server/__init__.py +0 -0
  391. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/server/broadcaster.py +0 -0
  392. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/server/core.py +0 -0
  393. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio/server/main.py +0 -0
  394. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio_client_manager.py +0 -0
  395. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/socketio_server.py +0 -0
  396. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/subprocess_launcher_service.py +0 -0
  397. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/ticket_manager.py +0 -0
  398. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/utility_service.py +0 -0
  399. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/__init__.py +0 -0
  400. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/branch_strategy.py +0 -0
  401. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/conflict_resolution.py +0 -0
  402. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/git_operations.py +0 -0
  403. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/semantic_versioning.py +0 -0
  404. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_control/version_parser.py +0 -0
  405. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/services/version_service.py +0 -0
  406. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/storage/__init__.py +0 -0
  407. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/storage/state_storage.py +0 -0
  408. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/ticket_wrapper.py +0 -0
  409. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/__init__.py +0 -0
  410. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/agent_dependency_loader.py +0 -0
  411. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/config_manager.py +0 -0
  412. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/console.py +0 -0
  413. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/dependency_cache.py +0 -0
  414. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/dependency_manager.py +0 -0
  415. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/dependency_strategies.py +0 -0
  416. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/environment_context.py +0 -0
  417. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/error_handler.py +0 -0
  418. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/file_utils.py +0 -0
  419. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/framework_detection.py +0 -0
  420. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/import_migration_example.py +0 -0
  421. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/imports.py +0 -0
  422. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/path_operations.py +0 -0
  423. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/robust_installer.py +0 -0
  424. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/session_logging.py +0 -0
  425. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/utils/subprocess_utils.py +0 -0
  426. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/validation/__init__.py +0 -0
  427. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/validation/agent_validator.py +0 -0
  428. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm/validation/frontmatter_validator.py +0 -0
  429. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm.egg-info/SOURCES.txt +0 -0
  430. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm.egg-info/dependency_links.txt +0 -0
  431. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm.egg-info/entry_points.txt +0 -0
  432. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm.egg-info/requires.txt +0 -0
  433. {claude_mpm-4.0.4 → claude_mpm-4.0.8}/src/claude_mpm.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 4.0.4
3
+ Version: 4.0.8
4
4
  Summary: Claude Multi-agent Project Manager - Clean orchestration with ticket management
5
5
  Home-page: https://github.com/bobmatnyc/claude-mpm
6
6
  Author: Claude MPM Team
@@ -0,0 +1 @@
1
+ 4.0.8
@@ -80,7 +80,7 @@ asyncio_mode = "auto"
80
80
 
81
81
  [tool.commitizen]
82
82
  name = "cz_conventional_commits"
83
- version = "4.0.4"
83
+ version = "4.0.8"
84
84
  version_files = [
85
85
  "VERSION",
86
86
  "package.json:version"
@@ -0,0 +1 @@
1
+ 4.0.8
@@ -1,4 +1,7 @@
1
- """Constants for Claude MPM."""
1
+ """Constants for Claude MPM.
2
+
3
+ Build number tracking is now enabled for all builds.
4
+ """
2
5
 
3
6
  from enum import Enum
4
7
  from pathlib import Path
@@ -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 PM memories from .claude-mpm/memories/PM.md.
289
+ Load actual memories from .claude-mpm/memories/ directory.
262
290
 
263
- These are the actual memories/knowledge that the PM should have,
264
- as opposed to the memory system instructions in MEMORY.md.
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
- memories_path = Path.cwd() / ".claude-mpm" / "memories" / "PM.md"
270
- if memories_path.exists():
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
- memories_path, "PM memories"
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.debug(f"PM memory size: {memory_size:,} bytes")
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 memories found at: {memories_path}")
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
- agents_dir = Path.cwd() / ".claude" / "agents"
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.exists():
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
@@ -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
- transformedEvent.type = 'system';
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=False,
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, # Disable auto-reconnect
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
- return client and client.connected
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
- self.connections = [
111
- conn
112
- for conn in self.connections
113
- if self._is_connection_alive(conn.get("client"))
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 logging.
438
+ """Emit Socket.IO event with improved reliability and persistent connections.
438
439
 
439
440
  WHY improved approach:
440
- - Better error handling and recovery
441
- - Comprehensive event logging for debugging
442
- - Automatic reconnection on failure
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
- return
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 with verification
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 status uncertain: hook.{event}",
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
- # Try to get a new client and emit again
511
- retry_port = int(os.environ.get("CLAUDE_MPM_SOCKETIO_PORT", "8765"))
512
- retry_client = self.connection_pool.get_connection(retry_port)
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}",
@@ -31,6 +31,8 @@ class SystemInstructionsService(BaseService, SystemInstructionsInterface):
31
31
  """
32
32
  super().__init__(name="system_instructions_service")
33
33
  self.agent_capabilities_service = agent_capabilities_service
34
+ self._framework_loader = None # Cache the framework loader instance
35
+ self._loaded_instructions = None # Cache loaded instructions
34
36
 
35
37
  async def _initialize(self) -> None:
36
38
  """Initialize the service. No special initialization needed."""
@@ -58,23 +60,36 @@ class SystemInstructionsService(BaseService, SystemInstructionsInterface):
58
60
  Processed system instructions string
59
61
  """
60
62
  try:
61
- # Use FrameworkLoader for comprehensive instruction loading
62
- from claude_mpm.core.framework_loader import FrameworkLoader
63
+ # Return cached instructions if already loaded
64
+ if self._loaded_instructions is not None:
65
+ self.logger.debug("Returning cached system instructions")
66
+ return self._loaded_instructions
63
67
 
64
- loader = FrameworkLoader()
65
- instructions = loader.get_framework_instructions()
68
+ # Create FrameworkLoader only once
69
+ if self._framework_loader is None:
70
+ from claude_mpm.core.framework_loader import FrameworkLoader
71
+ self._framework_loader = FrameworkLoader()
72
+ self.logger.debug("Created new FrameworkLoader instance")
73
+
74
+ # Load instructions and cache them
75
+ instructions = self._framework_loader.get_framework_instructions()
66
76
 
67
77
  if instructions:
68
- self.logger.info("Loaded framework instructions via FrameworkLoader")
78
+ self._loaded_instructions = instructions
79
+ self.logger.info("Loaded and cached framework instructions via FrameworkLoader")
69
80
  return instructions
70
81
 
71
82
  # Fallback if FrameworkLoader returns empty
72
83
  self.logger.warning("FrameworkLoader returned empty instructions, using fallback")
73
- return "# System Instructions\n\nNo specific system instructions found. Using default behavior."
84
+ fallback = "# System Instructions\n\nNo specific system instructions found. Using default behavior."
85
+ self._loaded_instructions = fallback
86
+ return fallback
74
87
 
75
88
  except Exception as e:
76
89
  self.logger.error(f"Failed to load system instructions: {e}")
77
- return "# System Instructions\n\nError loading system instructions. Using default behavior."
90
+ fallback = "# System Instructions\n\nError loading system instructions. Using default behavior."
91
+ self._loaded_instructions = fallback
92
+ return fallback
78
93
 
79
94
  def process_base_pm_content(self, base_pm_content: str) -> str:
80
95
  """Process BASE_PM.md content with dynamic injections.