claude-mpm 4.25.10__py3-none-any.whl → 5.1.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (507) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +1055 -2230
  4. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
  5. claude_mpm/agents/WORKFLOW.md +4 -4
  6. claude_mpm/agents/__init__.py +6 -0
  7. claude_mpm/agents/agent_loader.py +1 -4
  8. claude_mpm/agents/base_agent_loader.py +10 -35
  9. claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +576 -66
  10. claude_mpm/agents/templates/context-management-examples.md +544 -0
  11. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  12. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  13. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  14. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  15. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  16. claude_mpm/cli/__init__.py +28 -3
  17. claude_mpm/cli/commands/__init__.py +2 -0
  18. claude_mpm/cli/commands/agent_source.py +774 -0
  19. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  20. claude_mpm/cli/commands/agents.py +959 -36
  21. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  22. claude_mpm/cli/commands/agents_discover.py +338 -0
  23. claude_mpm/cli/commands/auto_configure.py +537 -239
  24. claude_mpm/cli/commands/config.py +7 -4
  25. claude_mpm/cli/commands/configure.py +924 -45
  26. claude_mpm/cli/commands/configure_navigation.py +63 -46
  27. claude_mpm/cli/commands/doctor.py +10 -2
  28. claude_mpm/cli/commands/local_deploy.py +1 -4
  29. claude_mpm/cli/commands/postmortem.py +401 -0
  30. claude_mpm/cli/commands/run.py +1 -39
  31. claude_mpm/cli/commands/skill_source.py +694 -0
  32. claude_mpm/cli/commands/skills.py +322 -19
  33. claude_mpm/cli/executor.py +22 -3
  34. claude_mpm/cli/interactive/agent_wizard.py +1028 -43
  35. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  36. claude_mpm/cli/parsers/agents_parser.py +256 -4
  37. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  38. claude_mpm/cli/parsers/base_parser.py +25 -0
  39. claude_mpm/cli/parsers/config_parser.py +96 -43
  40. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  41. claude_mpm/cli/parsers/skills_parser.py +7 -0
  42. claude_mpm/cli/parsers/source_parser.py +138 -0
  43. claude_mpm/cli/startup.py +456 -103
  44. claude_mpm/cli/startup_display.py +4 -4
  45. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  46. claude_mpm/commands/mpm-agents-detect.md +9 -0
  47. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  48. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  49. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  50. claude_mpm/commands/mpm-doctor.md +9 -0
  51. claude_mpm/commands/mpm-help.md +14 -2
  52. claude_mpm/commands/mpm-init.md +9 -0
  53. claude_mpm/commands/mpm-monitor.md +9 -0
  54. claude_mpm/commands/mpm-postmortem.md +123 -0
  55. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  56. claude_mpm/commands/mpm-status.md +9 -0
  57. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  58. claude_mpm/commands/mpm-ticket-view.md +552 -0
  59. claude_mpm/commands/mpm-version.md +9 -0
  60. claude_mpm/commands/mpm.md +10 -0
  61. claude_mpm/config/agent_presets.py +488 -0
  62. claude_mpm/config/agent_sources.py +325 -0
  63. claude_mpm/config/skill_presets.py +392 -0
  64. claude_mpm/config/skill_sources.py +590 -0
  65. claude_mpm/constants.py +1 -0
  66. claude_mpm/core/claude_runner.py +5 -34
  67. claude_mpm/core/config.py +16 -0
  68. claude_mpm/core/framework/__init__.py +3 -16
  69. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  70. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  71. claude_mpm/core/interactive_session.py +83 -7
  72. claude_mpm/core/oneshot_session.py +71 -8
  73. claude_mpm/core/protocols/__init__.py +23 -0
  74. claude_mpm/core/protocols/runner_protocol.py +103 -0
  75. claude_mpm/core/protocols/session_protocol.py +131 -0
  76. claude_mpm/core/shared/singleton_manager.py +11 -4
  77. claude_mpm/core/system_context.py +38 -0
  78. claude_mpm/core/unified_config.py +22 -0
  79. claude_mpm/experimental/cli_enhancements.py +1 -5
  80. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  87. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  88. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  89. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  90. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  91. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  92. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  93. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  94. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  95. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  96. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  97. claude_mpm/models/git_repository.py +198 -0
  98. claude_mpm/services/agents/agent_builder.py +45 -9
  99. claude_mpm/services/agents/agent_preset_service.py +238 -0
  100. claude_mpm/services/agents/agent_selection_service.py +484 -0
  101. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  102. claude_mpm/services/agents/cache_git_manager.py +621 -0
  103. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  104. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  105. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  106. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  107. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  108. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  109. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  110. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  111. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  112. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  113. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  114. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  115. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  116. claude_mpm/services/agents/git_source_manager.py +629 -0
  117. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -4
  118. claude_mpm/services/agents/local_template_manager.py +47 -9
  119. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  120. claude_mpm/services/agents/sources/__init__.py +13 -0
  121. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  122. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  123. claude_mpm/services/agents/startup_sync.py +239 -0
  124. claude_mpm/services/agents/toolchain_detector.py +474 -0
  125. claude_mpm/services/analysis/__init__.py +25 -0
  126. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  127. claude_mpm/services/analysis/postmortem_service.py +765 -0
  128. claude_mpm/services/command_deployment_service.py +200 -6
  129. claude_mpm/services/core/base.py +7 -2
  130. claude_mpm/services/core/interfaces/__init__.py +1 -3
  131. claude_mpm/services/core/interfaces/health.py +1 -4
  132. claude_mpm/services/core/models/__init__.py +2 -11
  133. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  134. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  135. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  136. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  137. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  138. claude_mpm/services/diagnostics/doctor_reporter.py +34 -6
  139. claude_mpm/services/git/__init__.py +21 -0
  140. claude_mpm/services/git/git_operations_service.py +494 -0
  141. claude_mpm/services/github/__init__.py +21 -0
  142. claude_mpm/services/github/github_cli_service.py +397 -0
  143. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  144. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  145. claude_mpm/services/instructions/__init__.py +9 -0
  146. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  147. claude_mpm/services/local_ops/__init__.py +3 -13
  148. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  149. claude_mpm/services/local_ops/health_manager.py +1 -4
  150. claude_mpm/services/mcp_config_manager.py +75 -145
  151. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  152. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  153. claude_mpm/services/mcp_service_verifier.py +6 -3
  154. claude_mpm/services/monitor/daemon.py +28 -8
  155. claude_mpm/services/monitor/daemon_manager.py +96 -19
  156. claude_mpm/services/pr/__init__.py +14 -0
  157. claude_mpm/services/pr/pr_template_service.py +329 -0
  158. claude_mpm/services/project/project_organizer.py +4 -0
  159. claude_mpm/services/runner_configuration_service.py +16 -3
  160. claude_mpm/services/session_management_service.py +16 -4
  161. claude_mpm/services/skills/__init__.py +18 -0
  162. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  163. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  164. claude_mpm/services/socketio/server/core.py +1 -4
  165. claude_mpm/services/socketio/server/main.py +1 -3
  166. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  167. claude_mpm/services/unified/unified_deployment.py +1 -5
  168. claude_mpm/services/visualization/__init__.py +1 -5
  169. claude_mpm/templates/questions/__init__.py +2 -7
  170. claude_mpm/templates/questions/pr_strategy.py +1 -4
  171. claude_mpm/templates/questions/project_init.py +1 -4
  172. claude_mpm/templates/questions/ticket_mgmt.py +1 -4
  173. claude_mpm/utils/agent_dependency_loader.py +77 -10
  174. claude_mpm/utils/agent_filters.py +288 -0
  175. claude_mpm/utils/gitignore.py +3 -0
  176. claude_mpm/utils/migration.py +372 -0
  177. claude_mpm/utils/progress.py +387 -0
  178. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +356 -112
  179. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +188 -439
  180. claude_mpm/agents/templates/agent-manager.json +0 -273
  181. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  182. claude_mpm/agents/templates/api_qa.json +0 -183
  183. claude_mpm/agents/templates/clerk-ops.json +0 -235
  184. claude_mpm/agents/templates/code_analyzer.json +0 -101
  185. claude_mpm/agents/templates/content-agent.json +0 -358
  186. claude_mpm/agents/templates/dart_engineer.json +0 -307
  187. claude_mpm/agents/templates/data_engineer.json +0 -225
  188. claude_mpm/agents/templates/documentation.json +0 -238
  189. claude_mpm/agents/templates/engineer.json +0 -210
  190. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  191. claude_mpm/agents/templates/golang_engineer.json +0 -270
  192. claude_mpm/agents/templates/imagemagick.json +0 -264
  193. claude_mpm/agents/templates/java_engineer.json +0 -346
  194. claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
  195. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  196. claude_mpm/agents/templates/memory_manager.json +0 -158
  197. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  198. claude_mpm/agents/templates/ops.json +0 -185
  199. claude_mpm/agents/templates/php-engineer.json +0 -287
  200. claude_mpm/agents/templates/product_owner.json +0 -338
  201. claude_mpm/agents/templates/project_organizer.json +0 -144
  202. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  203. claude_mpm/agents/templates/python_engineer.json +0 -387
  204. claude_mpm/agents/templates/qa.json +0 -243
  205. claude_mpm/agents/templates/react_engineer.json +0 -239
  206. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  207. claude_mpm/agents/templates/research.json +0 -258
  208. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  209. claude_mpm/agents/templates/rust_engineer.json +0 -275
  210. claude_mpm/agents/templates/security.json +0 -202
  211. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  212. claude_mpm/agents/templates/tauri_engineer.json +0 -274
  213. claude_mpm/agents/templates/ticketing.json +0 -181
  214. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  215. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  216. claude_mpm/agents/templates/version_control.json +0 -159
  217. claude_mpm/agents/templates/web_qa.json +0 -400
  218. claude_mpm/agents/templates/web_ui.json +0 -189
  219. claude_mpm/cli/README.md +0 -253
  220. claude_mpm/cli/commands/mcp_install_commands.py.backup +0 -284
  221. claude_mpm/cli/commands/mpm_init/README.md +0 -365
  222. claude_mpm/cli_module/refactoring_guide.md +0 -253
  223. claude_mpm/commands/mpm-tickets.md +0 -151
  224. claude_mpm/config/agent_capabilities.yaml +0 -658
  225. claude_mpm/config/async_logging_config.yaml +0 -145
  226. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
  227. claude_mpm/d2/.gitignore +0 -22
  228. claude_mpm/d2/ARCHITECTURE_COMPARISON.md +0 -273
  229. claude_mpm/d2/FLASK_INTEGRATION.md +0 -156
  230. claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +0 -452
  231. claude_mpm/d2/QUICKSTART.md +0 -186
  232. claude_mpm/d2/README.md +0 -232
  233. claude_mpm/d2/STORE_FIX_SUMMARY.md +0 -167
  234. claude_mpm/d2/SVELTE5_STORES_GUIDE.md +0 -180
  235. claude_mpm/d2/TESTING.md +0 -288
  236. claude_mpm/d2/index.html +0 -118
  237. claude_mpm/d2/package.json +0 -19
  238. claude_mpm/d2/src/App.svelte +0 -110
  239. claude_mpm/d2/src/components/Header.svelte +0 -153
  240. claude_mpm/d2/src/components/MainContent.svelte +0 -74
  241. claude_mpm/d2/src/components/Sidebar.svelte +0 -85
  242. claude_mpm/d2/src/components/tabs/EventsTab.svelte +0 -326
  243. claude_mpm/d2/src/lib/socketio.js +0 -144
  244. claude_mpm/d2/src/main.js +0 -7
  245. claude_mpm/d2/src/stores/events.js +0 -114
  246. claude_mpm/d2/src/stores/socket.js +0 -108
  247. claude_mpm/d2/src/stores/theme.js +0 -65
  248. claude_mpm/d2/svelte.config.js +0 -12
  249. claude_mpm/d2/vite.config.js +0 -15
  250. claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
  251. claude_mpm/dashboard/BUILD_NUMBER +0 -1
  252. claude_mpm/dashboard/README.md +0 -121
  253. claude_mpm/dashboard/VERSION +0 -1
  254. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  255. claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +0 -273
  256. claude_mpm/dashboard/react/components/ErrorBoundary.tsx +0 -75
  257. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  258. claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +0 -141
  259. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  260. claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +0 -36
  261. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  262. claude_mpm/dashboard/react/components/shared/FilterBar.tsx +0 -89
  263. claude_mpm/dashboard/react/contexts/DashboardContext.tsx +0 -215
  264. claude_mpm/dashboard/react/entries/events.tsx +0 -165
  265. claude_mpm/dashboard/react/hooks/useEvents.ts +0 -191
  266. claude_mpm/dashboard/react/hooks/useSocket.ts +0 -225
  267. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  268. claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +0 -170
  269. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  270. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  271. claude_mpm/dashboard/static/built/components/activity-tree.js.map +0 -1
  272. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  273. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  274. claude_mpm/dashboard/static/built/components/agent-inference.js.map +0 -1
  275. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  276. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  277. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  278. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  279. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  280. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  281. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  282. claude_mpm/dashboard/static/built/components/code-tree.js.map +0 -1
  283. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  284. claude_mpm/dashboard/static/built/components/code-viewer.js.map +0 -1
  285. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  286. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  287. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  288. claude_mpm/dashboard/static/built/components/event-processor.js.map +0 -1
  289. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  290. claude_mpm/dashboard/static/built/components/event-viewer.js.map +0 -1
  291. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  292. claude_mpm/dashboard/static/built/components/export-manager.js.map +0 -1
  293. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  294. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  295. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  296. claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +0 -1
  297. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  298. claude_mpm/dashboard/static/built/components/file-viewer.js.map +0 -1
  299. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  300. claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +0 -1
  301. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  302. claude_mpm/dashboard/static/built/components/hud-manager.js.map +0 -1
  303. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  304. claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +0 -1
  305. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  306. claude_mpm/dashboard/static/built/components/module-viewer.js.map +0 -1
  307. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  308. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  309. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  310. claude_mpm/dashboard/static/built/components/session-manager.js.map +0 -1
  311. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  312. claude_mpm/dashboard/static/built/components/socket-manager.js.map +0 -1
  313. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  314. claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +0 -1
  315. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  316. claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +0 -1
  317. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  318. claude_mpm/dashboard/static/built/components/working-directory.js.map +0 -1
  319. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  320. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  321. claude_mpm/dashboard/static/built/dashboard.js.map +0 -1
  322. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  323. claude_mpm/dashboard/static/built/react/events.js +0 -30
  324. claude_mpm/dashboard/static/built/react/events.js.map +0 -1
  325. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  326. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  327. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  328. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  329. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  330. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  331. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  332. claude_mpm/dashboard/static/built/socket-client.js.map +0 -1
  333. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  334. claude_mpm/dashboard/static/events.html +0 -607
  335. claude_mpm/dashboard/static/index.html +0 -635
  336. claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +0 -170
  337. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  338. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  339. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  340. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  341. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  342. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  343. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  344. claude_mpm/dashboard/static/legacy/files.html +0 -747
  345. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  346. claude_mpm/dashboard/static/monitors.html +0 -431
  347. claude_mpm/dashboard/static/navigation-test-results.md +0 -118
  348. claude_mpm/dashboard/static/production/events.html +0 -659
  349. claude_mpm/dashboard/static/production/main.html +0 -698
  350. claude_mpm/dashboard/static/production/monitors.html +0 -483
  351. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  352. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  353. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  354. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  355. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
  356. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
  357. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
  358. claude_mpm/hooks/README.md +0 -143
  359. claude_mpm/hooks/templates/README.md +0 -180
  360. claude_mpm/hooks/templates/settings.json.example +0 -147
  361. claude_mpm/schemas/agent_schema.json +0 -596
  362. claude_mpm/schemas/frontmatter_schema.json +0 -165
  363. claude_mpm/services/event_bus/README.md +0 -244
  364. claude_mpm/services/events/README.md +0 -303
  365. claude_mpm/services/framework_claude_md_generator/README.md +0 -119
  366. claude_mpm/services/mcp_gateway/README.md +0 -185
  367. claude_mpm/services/socketio/handlers/connection.py.backup +0 -217
  368. claude_mpm/services/socketio/handlers/hook.py.backup +0 -154
  369. claude_mpm/services/static/.gitkeep +0 -2
  370. claude_mpm/services/version_control/VERSION +0 -1
  371. claude_mpm/skills/bundled/.gitkeep +0 -2
  372. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  373. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  374. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  375. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  376. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  377. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  378. claude_mpm/skills/bundled/collaboration/git-worktrees.md +0 -317
  379. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  380. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  381. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  382. claude_mpm/skills/bundled/collaboration/stacked-prs.md +0 -251
  383. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  384. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  385. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  386. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  387. claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +0 -63
  388. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  389. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  390. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  391. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  392. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  393. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  394. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  395. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  396. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  397. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  398. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  399. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  400. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  401. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  402. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  403. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  404. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  405. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  406. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  407. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +0 -611
  408. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +0 -596
  409. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +0 -260
  410. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +0 -315
  411. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +0 -436
  412. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +0 -433
  413. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +0 -452
  414. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +0 -404
  415. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +0 -420
  416. claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +0 -202
  417. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  418. claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +0 -54
  419. claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +0 -322
  420. claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  421. claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +0 -202
  422. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  423. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  424. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  425. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  426. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  427. claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +0 -202
  428. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  429. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  430. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  431. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  432. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  433. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  434. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  435. claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +0 -22
  436. claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +0 -2
  437. claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +0 -202
  438. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  439. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  440. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  441. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  442. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  443. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  444. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  445. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  446. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  447. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  448. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  449. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  450. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  451. claude_mpm/skills/bundled/react/flexlayout-react.md +0 -742
  452. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  453. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  454. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  455. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  456. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  457. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  458. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  459. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +0 -495
  460. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +0 -599
  461. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +0 -535
  462. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +0 -613
  463. claude_mpm/skills/bundled/tauri/tauri-event-system.md +0 -648
  464. claude_mpm/skills/bundled/tauri/tauri-file-system.md +0 -673
  465. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +0 -767
  466. claude_mpm/skills/bundled/tauri/tauri-performance.md +0 -669
  467. claude_mpm/skills/bundled/tauri/tauri-state-management.md +0 -573
  468. claude_mpm/skills/bundled/tauri/tauri-testing.md +0 -384
  469. claude_mpm/skills/bundled/tauri/tauri-window-management.md +0 -628
  470. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  471. claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +0 -158
  472. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  473. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  474. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  475. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  476. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  477. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  478. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  479. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +0 -458
  480. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +0 -411
  481. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +0 -317
  482. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +0 -270
  483. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +0 -436
  484. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  485. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  486. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  487. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  488. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  489. claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +0 -202
  490. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  491. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  492. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  493. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  494. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  495. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  496. claude_mpm/templates/questions/EXAMPLES.md +0 -501
  497. claude_mpm/tools/README_SOCKETIO_DEBUG.md +0 -224
  498. claude_mpm/tools/code_tree_analyzer/README.md +0 -64
  499. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  500. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  501. /claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +0 -0
  502. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  503. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  504. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
  505. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
  506. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
  507. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
@@ -1,2 +0,0 @@
1
- import{E as e,E as r}from"./event-viewer.js";export{e as EventProcessor,r as default};
2
- //# sourceMappingURL=event-processor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-processor.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -1,2 +0,0 @@
1
- window.EventViewer=class{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()}),setTimeout(()=>{this.updateMetrics(),console.log("EventViewer: Initial metrics update")},200),setTimeout(()=>{this.updateMetrics(),console.log("EventViewer: Initial metrics update")},200)}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(){}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 o=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)}),o&&t.has(o)?e.value=o:o&&!t.has(o)&&(e.value="",this.typeFilter="")}updateDisplay(){this.updateEventTypeDropdown(),this.applyFilters(),this.events&&this.events.length>0&&!this.metricsInitialized&&(this.updateMetrics(),this.metricsInitialized=!0),this.events&&this.events.length>0&&!this.metricsInitialized&&(this.updateMetrics(),this.metricsInitialized=!0)}renderEvents(){const e=this.container;if(!e)return void console.warn("[EventViewer] Container not found, skipping render");if("events-list"!==e.id)return void console.error("[EventViewer] CRITICAL: Attempting to render to wrong container:",e.id);const t=e.closest(".tab-content");if(!t||"events-tab"!==t.id)return void console.error("[EventViewer] CRITICAL: events-list is not inside events-tab!");const n=document.getElementById("events-tab");if(!n||!n.classList.contains("active"))return void console.log("[EventViewer] Events tab not active, skipping render");const s=document.getElementById("claude-tree-tab");if(s&&s.classList.contains("active"))return void console.error("[EventViewer] CRITICAL: File Tree tab is active, blocking event render!");const o=e.scrollTop+e.clientHeight>=e.scrollHeight-10;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 i=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=i,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.filteredEvents.length>0&&o&&this.autoScroll&&requestAnimationFrame(()=>{e.scrollTop=e.scrollHeight})}formatEventType(e){return e.type&&e.subtype?e.type===e.subtype||"generic"===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);case"code":return this.formatCodeEvent(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 o=t.tool_name||"Unknown tool";return`<strong>Pre-Tool (${t.operation_type||"operation"}):</strong> ${o}`;case"post_tool":const i=t.tool_name||"Unknown tool";return`<strong>Post-Tool (${t.success?"success":t.status||"failed"}):</strong> ${i}${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_start":const a=t.agent_type||t.agent||t.subagent_type||"Unknown",l=t.prompt||t.description||t.task||"No description",d=l.length>60?l.substring(0,60)+"...":l;return`<strong>Subagent Start (${this.formatAgentType(a)}):</strong> ${d}`;case"subagent_stop":const c=t.agent_type||t.agent||t.subagent_type||"Unknown",p=t.reason||t.stop_reason||"completed",g=this.formatAgentType(c),u=t.structured_response?.task_completed;return`<strong>Subagent Stop (${g})${void 0!==u?u?" ✓":" ✗":""}:</strong> ${p}`;default:const h=t.hook_name||t.name||t.event_type||"Unknown";return`<strong>Hook ${e.subtype||n}:</strong> ${h}`}}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||"",o=s.length>80?s.substring(0,80)+"...":s;return`<strong>[${n.toUpperCase()}]</strong> ${o}`}formatCodeEvent(e){const t=e.data||{};if("progress"===e.subtype){const e=t.message||"Processing...",n=t.percentage;return void 0!==n?`<strong>Progress:</strong> ${e} (${Math.round(n)}%)`:`<strong>Progress:</strong> ${e}`}if("analysis:queued"===e.subtype)return`<strong>Queued:</strong> Analysis for ${t.path||"Unknown path"}`;if("analysis:start"===e.subtype)return`<strong>Started:</strong> Analyzing ${t.path||"Unknown path"}`;if("analysis:complete"===e.subtype){return`<strong>Complete:</strong> Analysis finished${t.duration?` (${t.duration.toFixed(2)}s)`:""}`}if("analysis:error"===e.subtype)return`<strong>Error:</strong> ${t.message||"Analysis failed"}`;if("analysis:cancelled"===e.subtype)return`<strong>Cancelled:</strong> Analysis stopped for ${t.path||"Unknown path"}`;if("file:start"===e.subtype)return`<strong>File:</strong> Processing ${t.file||"Unknown file"}`;if("file:complete"===e.subtype){const e=void 0!==t.nodes_count?` (${t.nodes_count} nodes)`:"";return`<strong>File done:</strong> ${t.file||"Unknown file"}${e}`}if("node:found"===e.subtype)return`<strong>Node:</strong> Found ${t.node_type||"element"} "${t.name||"unnamed"}"`;if("error"===e.subtype)return`<strong>Error:</strong> ${t.error||"Unknown error"} in ${t.file||"file"}`;const n=JSON.stringify(t);return`<strong>Code:</strong> ${n.length>100?n.substring(0,100)+"...":n}`}formatGenericEvent(e){const t=e.data;return"string"==typeof t?t.length>100?t.substring(0,100)+"...":t:JSON.stringify(t)}formatAgentType(e){const t={research:"Research",architect:"Architect",engineer:"Engineer",qa:"QA",pm:"PM",project_manager:"PM",research_agent:"Research",architect_agent:"Architect",engineer_agent:"Engineer",qa_agent:"QA",unknown:"Unknown"},n=(e||"unknown").toLowerCase();if(t[n])return t[n];const s=e.match(/^(\w+)(?:_agent|Agent)?$/i);return s&&s[1]?s[1].charAt(0).toUpperCase()+s[1].slice(1).toLowerCase():e.charAt(0).toUpperCase()+e.slice(1)}formatSingleRowEventContent(e){const t=this.formatEventType(e),n=e.data||{},s=e.source&&"system"!==e.source?`[${e.source}] `:"";let o="";switch(e.type){case"hook":const t=e.tool_name||n.tool_name||"Unknown",s=e.subtype||"Unknown";if("pre_tool"===s||"post_tool"===s){const e=n.operation_type||"",i="post_tool"===s&&void 0!==n.success?n.success?"✓":"✗":"";o=`${t}${e?` (${e})`:""}${i?` ${i}`:""}`}else if("user_prompt"===s){const e=n.prompt_text||n.prompt_preview||"";o=(e.length>60?e.substring(0,60)+"...":e)||"No prompt text"}else if("subagent_start"===s){const e=n.agent_type||n.agent||n.subagent_type||"Unknown",t=this.formatAgentType(e),s=n.prompt||n.description||n.task||"",i=s.length>40?s.substring(0,40)+"...":s;o=i?`${t} - ${i}`:t}else if("subagent_stop"===s){const e=n.agent_type||n.agent||n.subagent_type||"Unknown",t=this.formatAgentType(e),s=n.reason||n.stop_reason||"completed",i=n.structured_response?.task_completed,r=void 0!==i?i?"✓":"✗":"";o=`${t}${r?" "+r:""} - ${s}`}else if("stop"===s){const e=n.reason||"completed";o=`${n.stop_type||"normal"} - ${e}`}else o=t;break;case"agent":const i=e.subagent_type||n.subagent_type||"PM",r=n.status||"";o=`${i}${r?` - ${r}`:""}`;break;case"todo":if(n.todos&&Array.isArray(n.todos)){o=`${n.todos.length} items (${n.todos.filter(e=>"completed"===e.status).length} completed, ${n.todos.filter(e=>"in_progress"===e.status).length} in progress)`}else o="Todo update";break;case"memory":o=`${n.operation||"unknown"}: ${n.key||"unknown"}${n.value?` = ${JSON.stringify(n.value).substring(0,30)}...`:""}`;break;case"session":o=`ID: ${n.session_id||"unknown"}`;break;case"claude":if("request"===e.subtype){const e=n.prompt||n.message||"";o=(e.length>60?e.substring(0,60)+"...":e)||"Empty request"}else if("response"===e.subtype){const e=n.response||n.content||"";o=(e.length>60?e.substring(0,60)+"...":e)||"Empty response"}else o=n.message||"Claude interaction";break;case"log":const a=n.level||"info",l=n.message||"",d=l.length>60?l.substring(0,60)+"...":l;o=`[${a.toUpperCase()}] ${d}`;break;case"test":o=n.test_name||n.name||"Test";break;default:if("string"==typeof n)o=n.length>60?n.substring(0,60)+"...":n;else if(n.message)o=n.message.length>60?n.message.substring(0,60)+"...":n.message;else if(n.name)o=n.name;else if(Object.keys(n).length>0){const e=Object.keys(n).find(e=>!["timestamp","id"].includes(e));if(e){const t=n[e];o=`${e}: ${"object"==typeof t?JSON.stringify(t).substring(0,40)+"...":t}`}}}const i=`${s}${t}`;return o?`${i} - ${o}`:i}getHookDisplayName(e,t){const n={pre_tool:"Pre-Tool",post_tool:"Post-Tool",user_prompt:"User-Prompt",stop:"Stop",subagent_start:"Subagent-Start",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||"subagent_start"===e.subtype||"subagent_stop"===e.subtype?"agent_delegation":"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 o=[];if("Edit"===s){const t=e.tool_parameters||n.tool_parameters||{};t.old_string&&t.new_string&&o.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)&&(o=t.edits.map(e=>({...e,file_path:t.file_path||"unknown"})))}if(0===o.length)return"";const i=`edit-diff-${t}`,r=o.length>1;let a="";return o.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('${i}', event)">\n <span class="diff-toggle-icon">📋</span>\n <span class="diff-toggle-text">Show ${r?o.length+" edits":"edit"}</span>\n <span class="diff-toggle-arrow">▼</span>\n </div>\n <div id="${i}" 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 o="",i=0,r=0;for(;i<n.length||r<s.length;){const e=i<n.length?n[i]:null,t=r<s.length?s[r]:null;null===e?(o+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,r++):null===t?(o+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,i++):e===t?(o+=`<div class="diff-line diff-unchanged"> ${this.escapeHtml(e)}</div>`,i++,r++):(o+=`<div class="diff-line diff-removed">- ${this.escapeHtml(e)}</div>`,o+=`<div class="diff-line diff-added">+ ${this.escapeHtml(t)}</div>`,i++,r++)}return`<div class="diff-container">${o}</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}};class e{constructor(e,t){this.eventViewer=e,this.agentInference=t,this.agentEvents=[],this.filteredAgentEvents=[],this.filteredToolEvents=[],this.filteredFileEvents=[],this.selectedSessionId=null,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():"",o=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(o){if(!(e.agentName||"unknown").toLowerCase().includes(o.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():"",o=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(o){if((e.tool_name||"")!==o)return!1}return!0})}applyToolCallFilters(e){const t=document.getElementById("tools-search-input"),n=document.getElementById("tools-type-filter"),s=t?t.value.toLowerCase():"",o=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(o){if((t.tool_name||"")!==o)return!1}return!0})}applyFilesFilters(e){const t=document.getElementById("files-search-input"),n=document.getElementById("files-type-filter"),s=t?t.value.toLowerCase():"",o=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(o){if(!t.operations.map(e=>e.operation).includes(o))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),o=e.isImplied?"implied":"explicit",i=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} (${o}, ${i} 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",o=t.agent_type||"Unknown",i=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"===o.toLowerCase()?"pm":o})`}</span>\n <span class="event-timestamp">${i}</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),o=this.formatTimestamp(t.lastOperation),i={};s.forEach(e=>{i[e]=(i[e]||0)+1});const r=Object.entries(i).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">${o}</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)}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)}}window.EventProcessor=e;export{e as E};
2
- //# sourceMappingURL=event-viewer.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event-viewer.js","sources":["../../js/components/event-viewer.js","../../js/components/event-processor.js"],"sourcesContent":["/**\n * Event Viewer Component\n * Handles event display, filtering, and selection\n */\n\nclass EventViewer {\n constructor(containerId, socketClient) {\n this.container = document.getElementById(containerId);\n this.socketClient = socketClient;\n\n // State\n this.events = [];\n this.filteredEvents = [];\n this.selectedEventIndex = -1;\n this.filteredEventElements = [];\n this.autoScroll = true;\n\n // Filters\n this.searchFilter = '';\n this.typeFilter = '';\n this.sessionFilter = '';\n\n // Event type tracking\n this.eventTypeCount = {};\n this.availableEventTypes = new Set();\n this.errorCount = 0;\n this.eventsThisMinute = 0;\n this.lastMinute = new Date().getMinutes();\n\n this.init();\n }\n\n /**\n * Initialize the event viewer\n */\n init() {\n this.setupEventHandlers();\n this.setupKeyboardNavigation();\n\n // Subscribe to socket events\n this.socketClient.onEventUpdate((events, sessions) => {\n // Ensure we always have a valid events array\n this.events = Array.isArray(events) ? events : [];\n this.updateDisplay();\n });\n }\n\n /**\n * Setup event handlers for UI controls\n */\n setupEventHandlers() {\n // Search input\n const searchInput = document.getElementById('events-search-input');\n if (searchInput) {\n searchInput.addEventListener('input', (e) => {\n this.searchFilter = e.target.value.toLowerCase();\n this.applyFilters();\n });\n }\n\n // Type filter\n const typeFilter = document.getElementById('events-type-filter');\n if (typeFilter) {\n typeFilter.addEventListener('change', (e) => {\n this.typeFilter = e.target.value;\n this.applyFilters();\n });\n }\n }\n\n /**\n * Setup keyboard navigation for events\n * Note: This is now handled by the unified Dashboard navigation system\n */\n setupKeyboardNavigation() {\n // Keyboard navigation is now handled by Dashboard.setupUnifiedKeyboardNavigation()\n // This method is kept for backward compatibility but does nothing\n }\n\n /**\n * Handle arrow key navigation\n * @param {number} direction - Direction: 1 for down, -1 for up\n */\n handleArrowNavigation(direction) {\n if (this.filteredEventElements.length === 0) return;\n\n // Calculate new index\n let newIndex = this.selectedEventIndex + direction;\n\n // Wrap around\n if (newIndex >= this.filteredEventElements.length) {\n newIndex = 0;\n } else if (newIndex < 0) {\n newIndex = this.filteredEventElements.length - 1;\n }\n\n this.showEventDetails(newIndex);\n }\n\n /**\n * Apply filters to events\n */\n applyFilters() {\n // Defensive check to ensure events array exists\n if (!this.events || !Array.isArray(this.events)) {\n console.warn('EventViewer: events array is not initialized, using empty array');\n this.events = [];\n }\n\n this.filteredEvents = this.events.filter(event => {\n // NO AUTOMATIC FILTERING - All events are shown by default for complete visibility\n // Users can apply their own filters using the search and type filter controls\n \n // User-controlled search filter\n if (this.searchFilter) {\n const searchableText = [\n event.type || '',\n event.subtype || '',\n JSON.stringify(event.data || {})\n ].join(' ').toLowerCase();\n\n if (!searchableText.includes(this.searchFilter)) {\n return false;\n }\n }\n\n // User-controlled type filter - handles full hook types (like \"hook.user_prompt\") and main types\n if (this.typeFilter) {\n // Use the same logic as formatEventType to get the full event type\n const eventType = event.type && event.type.trim() !== '' ? event.type : '';\n const fullEventType = event.subtype && eventType ? `${eventType}.${event.subtype}` : eventType;\n if (fullEventType !== this.typeFilter) {\n return false;\n }\n }\n\n // User-controlled session filter\n if (this.sessionFilter && this.sessionFilter !== '') {\n if (!event.data || event.data.session_id !== this.sessionFilter) {\n return false;\n }\n }\n\n // Allow all events through unless filtered by user controls\n return true;\n });\n\n this.renderEvents();\n this.updateMetrics();\n }\n\n /**\n * Update available event types and populate dropdown\n */\n updateEventTypeDropdown() {\n const dropdown = document.getElementById('events-type-filter');\n if (!dropdown) return;\n\n // Extract unique event types from current events\n // Use the same logic as formatEventType to get full event type names\n const eventTypes = new Set();\n // Defensive check to ensure events array exists\n if (!this.events || !Array.isArray(this.events)) {\n console.warn('EventViewer: events array is not initialized in updateEventTypeDropdown');\n this.events = [];\n }\n\n this.events.forEach(event => {\n if (event.type && event.type.trim() !== '') {\n // Combine type and subtype if subtype exists, otherwise just use type\n const fullType = event.subtype ? `${event.type}.${event.subtype}` : event.type;\n eventTypes.add(fullType);\n }\n });\n\n // Check if event types have changed\n const currentTypes = Array.from(eventTypes).sort();\n const previousTypes = Array.from(this.availableEventTypes).sort();\n\n if (JSON.stringify(currentTypes) === JSON.stringify(previousTypes)) {\n return; // No change needed\n }\n\n // Update our tracking\n this.availableEventTypes = eventTypes;\n\n // Store the current selection\n const currentSelection = dropdown.value;\n\n // Clear existing options except \"All Events\"\n dropdown.innerHTML = '<option value=\"\">All Events</option>';\n\n // Add new options sorted alphabetically\n const sortedTypes = Array.from(eventTypes).sort();\n sortedTypes.forEach(type => {\n const option = document.createElement('option');\n option.value = type;\n option.textContent = type;\n dropdown.appendChild(option);\n });\n\n // Restore selection if it still exists\n if (currentSelection && eventTypes.has(currentSelection)) {\n dropdown.value = currentSelection;\n } else if (currentSelection && !eventTypes.has(currentSelection)) {\n // If the previously selected type no longer exists, clear the filter\n dropdown.value = '';\n this.typeFilter = '';\n }\n }\n\n /**\n * Update the display with current events\n */\n updateDisplay() {\n this.updateEventTypeDropdown();\n this.applyFilters();\n }\n\n /**\n * Render events in the UI\n */\n renderEvents() {\n // CRITICAL FIX: Use the container passed to constructor, not hardcoded events-list\n // This prevents events from being rendered in the wrong tab\n const eventsList = this.container;\n if (!eventsList) {\n console.warn('[EventViewer] Container not found, skipping render');\n return;\n }\n \n // CRITICAL SAFETY: Multiple checks to ensure events ONLY render in events-tab\n // Check 1: Verify we're rendering to the correct container\n if (eventsList.id !== 'events-list') {\n console.error('[EventViewer] CRITICAL: Attempting to render to wrong container:', eventsList.id);\n return;\n }\n \n // Check 2: Ensure events-list is inside events-tab\n const parentTab = eventsList.closest('.tab-content');\n if (!parentTab || parentTab.id !== 'events-tab') {\n console.error('[EventViewer] CRITICAL: events-list is not inside events-tab!');\n return;\n }\n \n // Check 3: Only render if Events tab is active\n const eventsTab = document.getElementById('events-tab');\n if (!eventsTab || !eventsTab.classList.contains('active')) {\n console.log('[EventViewer] Events tab not active, skipping render');\n return;\n }\n \n // Check 4: Ensure File Tree tab is not active\n const fileTreeTab = document.getElementById('claude-tree-tab');\n if (fileTreeTab && fileTreeTab.classList.contains('active')) {\n console.error('[EventViewer] CRITICAL: File Tree tab is active, blocking event render!');\n return;\n }\n\n // Check if user is at bottom BEFORE rendering (for autoscroll decision)\n const wasAtBottom = (eventsList.scrollTop + eventsList.clientHeight >= eventsList.scrollHeight - 10);\n\n if (this.filteredEvents.length === 0) {\n eventsList.innerHTML = `\n <div class=\"no-events\">\n ${this.events.length === 0 ?\n 'Connect to Socket.IO server to see events...' :\n 'No events match current filters...'}\n </div>\n `;\n this.filteredEventElements = [];\n return;\n }\n\n const html = this.filteredEvents.map((event, index) => {\n const timestamp = new Date(event.timestamp).toLocaleTimeString();\n const eventClass = event.type ? `event-${event.type}` : 'event-default';\n const isSelected = index === this.selectedEventIndex;\n\n // Get main content and timestamp separately\n const mainContent = this.formatSingleRowEventContent(event);\n\n // Check if this is an Edit/MultiEdit tool event and add diff viewer\n const diffViewer = this.createInlineEditDiffViewer(event, index);\n\n return `\n <div class=\"event-item single-row ${eventClass} ${isSelected ? 'selected' : ''}\"\n onclick=\"eventViewer.showEventDetails(${index})\"\n data-index=\"${index}\">\n <span class=\"event-single-row-content\">\n <span class=\"event-content-main\">${mainContent}</span>\n <span class=\"event-timestamp\">${timestamp}</span>\n </span>\n ${diffViewer}\n </div>\n `;\n }).join('');\n\n eventsList.innerHTML = html;\n\n // Update filtered elements reference\n this.filteredEventElements = Array.from(eventsList.querySelectorAll('.event-item'));\n\n // Update Dashboard navigation items if we're in the events tab\n if (window.dashboard && window.dashboard.currentTab === 'events' &&\n window.dashboard.tabNavigation && window.dashboard.tabNavigation.events) {\n window.dashboard.tabNavigation.events.items = this.filteredEventElements;\n }\n\n // Auto-scroll only if user was already at bottom before rendering\n if (this.filteredEvents.length > 0 && wasAtBottom && this.autoScroll) {\n // Use requestAnimationFrame to ensure DOM has updated\n requestAnimationFrame(() => {\n eventsList.scrollTop = eventsList.scrollHeight;\n });\n }\n }\n\n /**\n * Format event type for display\n * @param {Object} event - Event object\n * @returns {string} Formatted event type\n */\n formatEventType(event) {\n // If we have type and subtype, use them\n if (event.type && event.subtype) {\n // Check if type and subtype are identical or subtype is 'generic' to prevent redundant display\n if (event.type === event.subtype || event.subtype === 'generic') {\n return event.type;\n }\n return `${event.type}.${event.subtype}`;\n }\n // If we have just type, use it\n if (event.type) {\n return event.type;\n }\n // If we have originalEventName (from transformation), use it as fallback\n if (event.originalEventName) {\n return event.originalEventName;\n }\n // Last resort fallback\n return 'unknown';\n }\n\n /**\n * Format event data for display\n * @param {Object} event - Event object\n * @returns {string} Formatted event data\n */\n formatEventData(event) {\n if (!event.data) return 'No data';\n\n // Special formatting for different event types\n switch (event.type) {\n case 'session':\n return this.formatSessionEvent(event);\n case 'claude':\n return this.formatClaudeEvent(event);\n case 'agent':\n return this.formatAgentEvent(event);\n case 'hook':\n return this.formatHookEvent(event);\n case 'todo':\n return this.formatTodoEvent(event);\n case 'memory':\n return this.formatMemoryEvent(event);\n case 'log':\n return this.formatLogEvent(event);\n case 'code':\n return this.formatCodeEvent(event);\n default:\n return this.formatGenericEvent(event);\n }\n }\n\n /**\n * Format session event data\n */\n formatSessionEvent(event) {\n const data = event.data;\n if (event.subtype === 'started') {\n return `<strong>Session started:</strong> ${data.session_id || 'Unknown'}`;\n } else if (event.subtype === 'ended') {\n return `<strong>Session ended:</strong> ${data.session_id || 'Unknown'}`;\n }\n return `<strong>Session:</strong> ${JSON.stringify(data)}`;\n }\n\n /**\n * Format Claude event data\n */\n formatClaudeEvent(event) {\n const data = event.data;\n if (event.subtype === 'request') {\n const prompt = data.prompt || data.message || '';\n const truncated = prompt.length > 100 ? prompt.substring(0, 100) + '...' : prompt;\n return `<strong>Request:</strong> ${truncated}`;\n } else if (event.subtype === 'response') {\n const response = data.response || data.content || '';\n const truncated = response.length > 100 ? response.substring(0, 100) + '...' : response;\n return `<strong>Response:</strong> ${truncated}`;\n }\n return `<strong>Claude:</strong> ${JSON.stringify(data)}`;\n }\n\n /**\n * Format agent event data\n */\n formatAgentEvent(event) {\n const data = event.data;\n if (event.subtype === 'loaded') {\n return `<strong>Agent loaded:</strong> ${data.agent_type || data.name || 'Unknown'}`;\n } else if (event.subtype === 'executed') {\n return `<strong>Agent executed:</strong> ${data.agent_type || data.name || 'Unknown'}`;\n }\n return `<strong>Agent:</strong> ${JSON.stringify(data)}`;\n }\n\n /**\n * Format hook event data\n */\n formatHookEvent(event) {\n const data = event.data;\n const eventType = data.event_type || event.subtype || 'unknown';\n\n // Format based on specific hook event type\n switch (eventType) {\n case 'user_prompt':\n const prompt = data.prompt_text || data.prompt_preview || '';\n const truncated = prompt.length > 80 ? prompt.substring(0, 80) + '...' : prompt;\n return `<strong>User Prompt:</strong> ${truncated || 'No prompt text'}`;\n\n case 'pre_tool':\n const toolName = data.tool_name || 'Unknown tool';\n const operation = data.operation_type || 'operation';\n return `<strong>Pre-Tool (${operation}):</strong> ${toolName}`;\n\n case 'post_tool':\n const postToolName = data.tool_name || 'Unknown tool';\n const status = data.success ? 'success' : data.status || 'failed';\n const duration = data.duration_ms ? ` (${data.duration_ms}ms)` : '';\n return `<strong>Post-Tool (${status}):</strong> ${postToolName}${duration}`;\n\n case 'notification':\n const notifType = data.notification_type || 'notification';\n const message = data.message_preview || data.message || 'No message';\n return `<strong>Notification (${notifType}):</strong> ${message}`;\n\n case 'stop':\n const reason = data.reason || 'unknown';\n const stopType = data.stop_type || 'normal';\n return `<strong>Stop (${stopType}):</strong> ${reason}`;\n\n case 'subagent_start':\n // Try multiple locations for agent type\n const startAgentType = data.agent_type || data.agent || data.subagent_type || 'Unknown';\n const startPrompt = data.prompt || data.description || data.task || 'No description';\n const startTruncated = startPrompt.length > 60 ? startPrompt.substring(0, 60) + '...' : startPrompt;\n // Format with proper agent type display\n const startAgentDisplay = this.formatAgentType(startAgentType);\n return `<strong>Subagent Start (${startAgentDisplay}):</strong> ${startTruncated}`;\n\n case 'subagent_stop':\n // Try multiple locations for agent type\n const agentType = data.agent_type || data.agent || data.subagent_type || 'Unknown';\n const stopReason = data.reason || data.stop_reason || 'completed';\n // Format with proper agent type display\n const stopAgentDisplay = this.formatAgentType(agentType);\n // Include task completion status if available\n const isCompleted = data.structured_response?.task_completed;\n const completionStatus = isCompleted !== undefined ? (isCompleted ? ' ✓' : ' ✗') : '';\n return `<strong>Subagent Stop (${stopAgentDisplay})${completionStatus}:</strong> ${stopReason}`;\n\n default:\n // Fallback to original logic for unknown hook types\n const hookName = data.hook_name || data.name || data.event_type || 'Unknown';\n const phase = event.subtype || eventType;\n return `<strong>Hook ${phase}:</strong> ${hookName}`;\n }\n }\n\n /**\n * Format todo event data\n */\n formatTodoEvent(event) {\n const data = event.data;\n if (data.todos && Array.isArray(data.todos)) {\n const count = data.todos.length;\n return `<strong>Todo updated:</strong> ${count} item${count !== 1 ? 's' : ''}`;\n }\n return `<strong>Todo:</strong> ${JSON.stringify(data)}`;\n }\n\n /**\n * Format memory event data\n */\n formatMemoryEvent(event) {\n const data = event.data;\n const operation = data.operation || 'unknown';\n return `<strong>Memory ${operation}:</strong> ${data.key || 'Unknown key'}`;\n }\n\n /**\n * Format log event data\n */\n formatLogEvent(event) {\n const data = event.data;\n const level = data.level || 'info';\n const message = data.message || '';\n const truncated = message.length > 80 ? message.substring(0, 80) + '...' : message;\n return `<strong>[${level.toUpperCase()}]</strong> ${truncated}`;\n }\n\n /**\n * Format code analysis event data\n */\n formatCodeEvent(event) {\n const data = event.data || {};\n \n // Handle different code event subtypes\n if (event.subtype === 'progress') {\n const message = data.message || 'Processing...';\n const percentage = data.percentage;\n if (percentage !== undefined) {\n return `<strong>Progress:</strong> ${message} (${Math.round(percentage)}%)`;\n }\n return `<strong>Progress:</strong> ${message}`;\n } else if (event.subtype === 'analysis:queued') {\n return `<strong>Queued:</strong> Analysis for ${data.path || 'Unknown path'}`;\n } else if (event.subtype === 'analysis:start') {\n return `<strong>Started:</strong> Analyzing ${data.path || 'Unknown path'}`;\n } else if (event.subtype === 'analysis:complete') {\n const duration = data.duration ? ` (${data.duration.toFixed(2)}s)` : '';\n return `<strong>Complete:</strong> Analysis finished${duration}`;\n } else if (event.subtype === 'analysis:error') {\n return `<strong>Error:</strong> ${data.message || 'Analysis failed'}`;\n } else if (event.subtype === 'analysis:cancelled') {\n return `<strong>Cancelled:</strong> Analysis stopped for ${data.path || 'Unknown path'}`;\n } else if (event.subtype === 'file:start') {\n return `<strong>File:</strong> Processing ${data.file || 'Unknown file'}`;\n } else if (event.subtype === 'file:complete') {\n const nodes = data.nodes_count !== undefined ? ` (${data.nodes_count} nodes)` : '';\n return `<strong>File done:</strong> ${data.file || 'Unknown file'}${nodes}`;\n } else if (event.subtype === 'node:found') {\n return `<strong>Node:</strong> Found ${data.node_type || 'element'} \"${data.name || 'unnamed'}\"`;\n } else if (event.subtype === 'error') {\n return `<strong>Error:</strong> ${data.error || 'Unknown error'} in ${data.file || 'file'}`;\n }\n \n // Generic fallback for code events\n const json = JSON.stringify(data);\n return `<strong>Code:</strong> ${json.length > 100 ? json.substring(0, 100) + '...' : json}`;\n }\n\n /**\n * Format generic event data\n */\n formatGenericEvent(event) {\n const data = event.data;\n if (typeof data === 'string') {\n return data.length > 100 ? data.substring(0, 100) + '...' : data;\n }\n return JSON.stringify(data);\n }\n\n /**\n * Format agent type for display with proper capitalization\n * @param {string} agentType - The raw agent type string\n * @returns {string} Formatted agent type for display\n */\n formatAgentType(agentType) {\n // Handle common agent type patterns\n const agentTypeMap = {\n 'research': 'Research',\n 'architect': 'Architect',\n 'engineer': 'Engineer',\n 'qa': 'QA',\n 'pm': 'PM',\n 'project_manager': 'PM',\n 'research_agent': 'Research',\n 'architect_agent': 'Architect',\n 'engineer_agent': 'Engineer',\n 'qa_agent': 'QA',\n 'unknown': 'Unknown'\n };\n \n // Try to find a match in the map (case-insensitive)\n const lowerType = (agentType || 'unknown').toLowerCase();\n if (agentTypeMap[lowerType]) {\n return agentTypeMap[lowerType];\n }\n \n // If not in map, try to extract the agent name from patterns like \"Research Agent\" or \"research_agent\"\n const match = agentType.match(/^(\\w+)(?:_agent|Agent)?$/i);\n if (match && match[1]) {\n // Capitalize first letter\n return match[1].charAt(0).toUpperCase() + match[1].slice(1).toLowerCase();\n }\n \n // Fallback: just capitalize first letter of whatever we have\n return agentType.charAt(0).toUpperCase() + agentType.slice(1);\n }\n\n /**\n * Format event content for single-row display (without timestamp)\n * Format: \"{type}.{subtype}\" followed by data details\n * @param {Object} event - Event object\n * @returns {string} Formatted single-row event content string\n */\n formatSingleRowEventContent(event) {\n const eventType = this.formatEventType(event);\n const data = event.data || {};\n \n // Include source if it's not the default 'system' source\n const sourcePrefix = event.source && event.source !== 'system' ? `[${event.source}] ` : '';\n\n // Extract meaningful details from the data package for different event types\n let dataDetails = '';\n\n switch (event.type) {\n case 'hook':\n // Hook events: show tool name and operation details\n const toolName = event.tool_name || data.tool_name || 'Unknown';\n const hookType = event.subtype || 'Unknown';\n \n // Format specific hook types\n if (hookType === 'pre_tool' || hookType === 'post_tool') {\n const operation = data.operation_type || '';\n const status = hookType === 'post_tool' && data.success !== undefined \n ? (data.success ? '✓' : '✗') \n : '';\n dataDetails = `${toolName}${operation ? ` (${operation})` : ''}${status ? ` ${status}` : ''}`;\n } else if (hookType === 'user_prompt') {\n const prompt = data.prompt_text || data.prompt_preview || '';\n const truncated = prompt.length > 60 ? prompt.substring(0, 60) + '...' : prompt;\n dataDetails = truncated || 'No prompt text';\n } else if (hookType === 'subagent_start') {\n // Enhanced agent type detection\n const agentType = data.agent_type || data.agent || data.subagent_type || 'Unknown';\n const agentDisplay = this.formatAgentType(agentType);\n const prompt = data.prompt || data.description || data.task || '';\n const truncated = prompt.length > 40 ? prompt.substring(0, 40) + '...' : prompt;\n dataDetails = truncated ? `${agentDisplay} - ${truncated}` : agentDisplay;\n } else if (hookType === 'subagent_stop') {\n // Enhanced agent type detection for subagent_stop\n const agentType = data.agent_type || data.agent || data.subagent_type || 'Unknown';\n const agentDisplay = this.formatAgentType(agentType);\n const reason = data.reason || data.stop_reason || 'completed';\n const isCompleted = data.structured_response?.task_completed;\n const status = isCompleted !== undefined ? (isCompleted ? '✓' : '✗') : '';\n dataDetails = `${agentDisplay}${status ? ' ' + status : ''} - ${reason}`;\n } else if (hookType === 'stop') {\n const reason = data.reason || 'completed';\n const stopType = data.stop_type || 'normal';\n dataDetails = `${stopType} - ${reason}`;\n } else {\n dataDetails = toolName;\n }\n break;\n\n case 'agent':\n // Agent events: show agent name and status\n const agentName = event.subagent_type || data.subagent_type || 'PM';\n const status = data.status || '';\n dataDetails = `${agentName}${status ? ` - ${status}` : ''}`;\n break;\n\n case 'todo':\n // Todo events: show item count and status changes\n if (data.todos && Array.isArray(data.todos)) {\n const count = data.todos.length;\n const completed = data.todos.filter(t => t.status === 'completed').length;\n const inProgress = data.todos.filter(t => t.status === 'in_progress').length;\n dataDetails = `${count} items (${completed} completed, ${inProgress} in progress)`;\n } else {\n dataDetails = 'Todo update';\n }\n break;\n\n case 'memory':\n // Memory events: show operation and key\n const operation = data.operation || 'unknown';\n const key = data.key || 'unknown';\n const value = data.value ? ` = ${JSON.stringify(data.value).substring(0, 30)}...` : '';\n dataDetails = `${operation}: ${key}${value}`;\n break;\n\n case 'session':\n // Session events: show session ID\n const sessionId = data.session_id || 'unknown';\n dataDetails = `ID: ${sessionId}`;\n break;\n\n case 'claude':\n // Claude events: show request/response preview\n if (event.subtype === 'request') {\n const prompt = data.prompt || data.message || '';\n const truncated = prompt.length > 60 ? prompt.substring(0, 60) + '...' : prompt;\n dataDetails = truncated || 'Empty request';\n } else if (event.subtype === 'response') {\n const response = data.response || data.content || '';\n const truncated = response.length > 60 ? response.substring(0, 60) + '...' : response;\n dataDetails = truncated || 'Empty response';\n } else {\n dataDetails = data.message || 'Claude interaction';\n }\n break;\n\n case 'log':\n // Log events: show log level and message\n const level = data.level || 'info';\n const message = data.message || '';\n const truncated = message.length > 60 ? message.substring(0, 60) + '...' : message;\n dataDetails = `[${level.toUpperCase()}] ${truncated}`;\n break;\n\n case 'test':\n // Test events: show test name or details\n const testName = data.test_name || data.name || 'Test';\n dataDetails = testName;\n break;\n\n default:\n // Generic events: show any available data\n if (typeof data === 'string') {\n dataDetails = data.length > 60 ? data.substring(0, 60) + '...' : data;\n } else if (data.message) {\n dataDetails = data.message.length > 60 ? data.message.substring(0, 60) + '...' : data.message;\n } else if (data.name) {\n dataDetails = data.name;\n } else if (Object.keys(data).length > 0) {\n // Show first meaningful field from data\n const firstKey = Object.keys(data).find(k => !['timestamp', 'id'].includes(k));\n if (firstKey) {\n const value = data[firstKey];\n dataDetails = `${firstKey}: ${typeof value === 'object' ? JSON.stringify(value).substring(0, 40) + '...' : value}`;\n }\n }\n break;\n }\n\n // Return formatted string: \"[source] {type}.{subtype} - {data details}\"\n // The eventType already contains the type.subtype format from formatEventType()\n const fullType = `${sourcePrefix}${eventType}`;\n return dataDetails ? `${fullType} - ${dataDetails}` : fullType;\n }\n\n /**\n * Get display name for hook types\n * @param {string} hookType - Hook subtype\n * @param {Object} data - Event data\n * @returns {string} Display name\n */\n getHookDisplayName(hookType, data) {\n const hookNames = {\n 'pre_tool': 'Pre-Tool',\n 'post_tool': 'Post-Tool',\n 'user_prompt': 'User-Prompt',\n 'stop': 'Stop',\n 'subagent_start': 'Subagent-Start',\n 'subagent_stop': 'Subagent-Stop',\n 'notification': 'Notification'\n };\n\n // Handle non-string hookType safely\n if (hookNames[hookType]) {\n return hookNames[hookType];\n }\n \n // Convert to string and handle null/undefined\n const typeStr = String(hookType || 'unknown');\n return typeStr.replace(/_/g, ' ');\n }\n\n /**\n * Get event category for display\n * @param {Object} event - Event object\n * @returns {string} Category\n */\n getEventCategory(event) {\n const data = event.data || {};\n const toolName = event.tool_name || data.tool_name || '';\n\n // Categorize based on tool type\n if (['Read', 'Write', 'Edit', 'MultiEdit'].includes(toolName)) {\n return 'file_operations';\n } else if (['Bash', 'grep', 'Glob'].includes(toolName)) {\n return 'system_operations';\n } else if (toolName === 'TodoWrite') {\n return 'task_management';\n } else if (toolName === 'Task') {\n return 'agent_delegation';\n } else if (event.subtype === 'subagent_start' || event.subtype === 'subagent_stop') {\n return 'agent_delegation';\n } else if (event.subtype === 'stop') {\n return 'session_control';\n }\n\n return 'general';\n }\n\n /**\n * Show event details and update selection\n * @param {number} index - Index of event to show\n */\n showEventDetails(index) {\n // Defensive checks\n if (!this.filteredEvents || !Array.isArray(this.filteredEvents)) {\n console.warn('EventViewer: filteredEvents array is not initialized');\n return;\n }\n if (index < 0 || index >= this.filteredEvents.length) return;\n\n // Update selection\n this.selectedEventIndex = index;\n\n // Get the selected event\n const event = this.filteredEvents[index];\n\n // Coordinate with Dashboard unified navigation system\n if (window.dashboard) {\n // Update the dashboard's navigation state for events tab\n if (window.dashboard.tabNavigation && window.dashboard.tabNavigation.events) {\n window.dashboard.tabNavigation.events.selectedIndex = index;\n }\n if (window.dashboard.selectCard) {\n window.dashboard.selectCard('events', index, 'event', event);\n }\n }\n\n // Update visual selection (this will be handled by Dashboard.updateCardSelectionUI())\n this.filteredEventElements.forEach((el, i) => {\n el.classList.toggle('selected', i === index);\n });\n\n // Notify other components about selection\n document.dispatchEvent(new CustomEvent('eventSelected', {\n detail: { event, index }\n }));\n\n // Scroll to selected event if not visible\n const selectedElement = this.filteredEventElements[index];\n if (selectedElement) {\n selectedElement.scrollIntoView({\n behavior: 'smooth',\n block: 'nearest'\n });\n }\n }\n\n /**\n * Clear event selection\n */\n clearSelection() {\n this.selectedEventIndex = -1;\n this.filteredEventElements.forEach(el => {\n el.classList.remove('selected');\n });\n\n // Coordinate with Dashboard unified navigation system\n if (window.dashboard) {\n if (window.dashboard.tabNavigation && window.dashboard.tabNavigation.events) {\n window.dashboard.tabNavigation.events.selectedIndex = -1;\n }\n if (window.dashboard.clearCardSelection) {\n window.dashboard.clearCardSelection();\n }\n }\n\n // Notify other components\n document.dispatchEvent(new CustomEvent('eventSelectionCleared'));\n }\n\n /**\n * Update metrics display\n */\n updateMetrics() {\n // Update event type counts\n this.eventTypeCount = {};\n this.errorCount = 0;\n\n // Defensive check to ensure events array exists\n if (!this.events || !Array.isArray(this.events)) {\n console.warn('EventViewer: events array is not initialized in updateMetrics');\n this.events = [];\n }\n\n this.events.forEach(event => {\n const type = event.type || 'unknown';\n this.eventTypeCount[type] = (this.eventTypeCount[type] || 0) + 1;\n\n if (event.type === 'log' &&\n event.data &&\n ['error', 'critical'].includes(event.data.level)) {\n this.errorCount++;\n }\n });\n\n // Update events per minute\n const currentMinute = new Date().getMinutes();\n if (currentMinute !== this.lastMinute) {\n this.lastMinute = currentMinute;\n this.eventsThisMinute = 0;\n }\n\n // Count events in the last minute\n const oneMinuteAgo = new Date(Date.now() - 60000);\n this.eventsThisMinute = this.events.filter(event =>\n new Date(event.timestamp) > oneMinuteAgo\n ).length;\n\n // Update UI\n this.updateMetricsUI();\n }\n\n /**\n * Update metrics in the UI\n */\n updateMetricsUI() {\n const totalEventsEl = document.getElementById('total-events');\n const eventsPerMinuteEl = document.getElementById('events-per-minute');\n const uniqueTypesEl = document.getElementById('unique-types');\n const errorCountEl = document.getElementById('error-count');\n\n if (totalEventsEl) totalEventsEl.textContent = this.events.length;\n if (eventsPerMinuteEl) eventsPerMinuteEl.textContent = this.eventsThisMinute;\n if (uniqueTypesEl) uniqueTypesEl.textContent = Object.keys(this.eventTypeCount).length;\n if (errorCountEl) errorCountEl.textContent = this.errorCount;\n }\n\n /**\n * Export events to JSON\n */\n exportEvents() {\n const dataStr = JSON.stringify(this.filteredEvents, null, 2);\n const dataBlob = new Blob([dataStr], { type: 'application/json' });\n const url = URL.createObjectURL(dataBlob);\n\n const link = document.createElement('a');\n link.href = url;\n link.download = `claude-mpm-events-${new Date().toISOString().split('T')[0]}.json`;\n link.click();\n\n URL.revokeObjectURL(url);\n }\n\n /**\n * Clear all events\n */\n clearEvents() {\n this.socketClient.clearEvents();\n this.selectedEventIndex = -1;\n this.updateDisplay();\n }\n\n /**\n * Set session filter\n * @param {string} sessionId - Session ID to filter by\n */\n setSessionFilter(sessionId) {\n this.sessionFilter = sessionId;\n this.applyFilters();\n }\n\n /**\n * Get current filter state\n * @returns {Object} Current filters\n */\n getFilters() {\n return {\n search: this.searchFilter,\n type: this.typeFilter,\n session: this.sessionFilter\n };\n }\n\n /**\n * Get filtered events (used by HUD and other components)\n * @returns {Array} Array of filtered events\n */\n getFilteredEvents() {\n return this.filteredEvents;\n }\n\n /**\n * Get all events (unfiltered, used by HUD for complete visualization)\n * @returns {Array} Array of all events\n */\n getAllEvents() {\n return this.events;\n }\n\n /**\n * Create inline diff viewer for Edit/MultiEdit tool events\n * WHY: Provides immediate visibility of file changes without needing to open modals\n * DESIGN DECISION: Shows inline diffs only for Edit/MultiEdit events to avoid clutter\n * @param {Object} event - Event object\n * @param {number} index - Event index for unique IDs\n * @returns {string} HTML for inline diff viewer\n */\n createInlineEditDiffViewer(event, index) {\n const data = event.data || {};\n const toolName = event.tool_name || data.tool_name || '';\n\n // Only show for Edit and MultiEdit tools\n if (!['Edit', 'MultiEdit'].includes(toolName)) {\n return '';\n }\n\n // Extract edit parameters based on tool type\n let edits = [];\n if (toolName === 'Edit') {\n // Single edit\n const parameters = event.tool_parameters || data.tool_parameters || {};\n if (parameters.old_string && parameters.new_string) {\n edits.push({\n old_string: parameters.old_string,\n new_string: parameters.new_string,\n file_path: parameters.file_path || 'unknown'\n });\n }\n } else if (toolName === 'MultiEdit') {\n // Multiple edits\n const parameters = event.tool_parameters || data.tool_parameters || {};\n if (parameters.edits && Array.isArray(parameters.edits)) {\n edits = parameters.edits.map(edit => ({\n ...edit,\n file_path: parameters.file_path || 'unknown'\n }));\n }\n }\n\n if (edits.length === 0) {\n return '';\n }\n\n // Create collapsible diff section\n const diffId = `edit-diff-${index}`;\n const isMultiEdit = edits.length > 1;\n\n let diffContent = '';\n edits.forEach((edit, editIndex) => {\n const editId = `${diffId}-${editIndex}`;\n const diffHtml = this.createDiffHtml(edit.old_string, edit.new_string);\n\n diffContent += `\n <div class=\"edit-diff-section\">\n ${isMultiEdit ? `<div class=\"edit-diff-header\">Edit ${editIndex + 1}</div>` : ''}\n <div class=\"diff-content\">${diffHtml}</div>\n </div>\n `;\n });\n\n return `\n <div class=\"inline-edit-diff-viewer\">\n <div class=\"diff-toggle-header\" onclick=\"eventViewer.toggleEditDiff('${diffId}', event)\">\n <span class=\"diff-toggle-icon\">📋</span>\n <span class=\"diff-toggle-text\">Show ${isMultiEdit ? edits.length + ' edits' : 'edit'}</span>\n <span class=\"diff-toggle-arrow\">▼</span>\n </div>\n <div id=\"${diffId}\" class=\"diff-content-container\" style=\"display: none;\">\n ${diffContent}\n </div>\n </div>\n `;\n }\n\n /**\n * Create HTML diff visualization\n * WHY: Provides clear visual representation of text changes similar to git diff\n * @param {string} oldText - Original text\n * @param {string} newText - Modified text\n * @returns {string} HTML diff content\n */\n createDiffHtml(oldText, newText) {\n // Simple line-by-line diff implementation\n const oldLines = oldText.split('\\n');\n const newLines = newText.split('\\n');\n\n let diffHtml = '';\n let i = 0, j = 0;\n\n // Simple diff algorithm - can be enhanced with proper diff library if needed\n while (i < oldLines.length || j < newLines.length) {\n const oldLine = i < oldLines.length ? oldLines[i] : null;\n const newLine = j < newLines.length ? newLines[j] : null;\n\n if (oldLine === null) {\n // New line added\n diffHtml += `<div class=\"diff-line diff-added\">+ ${this.escapeHtml(newLine)}</div>`;\n j++;\n } else if (newLine === null) {\n // Old line removed\n diffHtml += `<div class=\"diff-line diff-removed\">- ${this.escapeHtml(oldLine)}</div>`;\n i++;\n } else if (oldLine === newLine) {\n // Lines are the same\n diffHtml += `<div class=\"diff-line diff-unchanged\"> ${this.escapeHtml(oldLine)}</div>`;\n i++;\n j++;\n } else {\n // Lines are different - show both\n diffHtml += `<div class=\"diff-line diff-removed\">- ${this.escapeHtml(oldLine)}</div>`;\n diffHtml += `<div class=\"diff-line diff-added\">+ ${this.escapeHtml(newLine)}</div>`;\n i++;\n j++;\n }\n }\n\n return `<div class=\"diff-container\">${diffHtml}</div>`;\n }\n\n /**\n * Toggle edit diff visibility\n * @param {string} diffId - Diff container ID\n * @param {Event} event - Click event\n */\n toggleEditDiff(diffId, event) {\n // Prevent event bubbling to parent event item\n event.stopPropagation();\n\n const diffContainer = document.getElementById(diffId);\n const arrow = event.currentTarget.querySelector('.diff-toggle-arrow');\n\n if (diffContainer) {\n const isVisible = diffContainer.style.display !== 'none';\n diffContainer.style.display = isVisible ? 'none' : 'block';\n if (arrow) {\n arrow.textContent = isVisible ? '▼' : '▲';\n }\n }\n }\n\n /**\n * Escape HTML characters for safe display\n * @param {string} text - Text to escape\n * @returns {string} Escaped text\n */\n escapeHtml(text) {\n const div = document.createElement('div');\n div.textContent = text;\n return div.innerHTML;\n }\n}\n\n// ES6 Module export\nexport { EventViewer };\nexport default EventViewer;\n\n// Backward compatibility - keep window export for non-module usage\nwindow.EventViewer = EventViewer;\n","/**\n * Event Processor Module\n *\n * Handles event processing, filtering, and rendering for different tabs in the dashboard.\n * Provides centralized event filtering and rendering logic for agents, tools, and files tabs.\n *\n * WHY: Extracted from main dashboard to isolate complex event processing logic\n * that involves filtering, transforming, and rendering events across different views.\n * This improves maintainability and makes the event processing logic testable.\n *\n * DESIGN DECISION: Maintains its own filtered event collections while relying on\n * eventViewer for source data. Provides separate filtering logic for each tab type\n * while sharing common filtering patterns and utilities.\n */\nclass EventProcessor {\n constructor(eventViewer, agentInference) {\n this.eventViewer = eventViewer;\n this.agentInference = agentInference;\n\n // Processed event collections for different tabs\n this.agentEvents = [];\n this.filteredAgentEvents = [];\n this.filteredToolEvents = [];\n this.filteredFileEvents = [];\n\n // Session filtering\n this.selectedSessionId = null;\n\n console.log('Event processor initialized');\n }\n\n /**\n * Get filtered events for a specific tab\n * @param {string} tabName - Tab name ('agents', 'tools', 'files', 'events')\n * @returns {Array} - Filtered events\n */\n getFilteredEventsForTab(tabName) {\n const events = this.eventViewer.events;\n console.log(`getFilteredEventsForTab(${tabName}) - using RAW events: ${events.length} total`);\n\n // Use session manager to filter events by session if needed\n const sessionManager = window.sessionManager;\n if (sessionManager && sessionManager.selectedSessionId) {\n const sessionEvents = sessionManager.getEventsForSession(sessionManager.selectedSessionId);\n console.log(`Filtering by session ${sessionManager.selectedSessionId}: ${sessionEvents.length} events`);\n return sessionEvents;\n }\n\n return events;\n }\n\n /**\n * Apply agents tab filtering for unique instances\n * @param {Array} uniqueInstances - Unique agent instances to filter\n * @returns {Array} - Filtered unique instances\n */\n applyAgentsFilters(uniqueInstances) {\n const searchInput = document.getElementById('agents-search-input');\n const typeFilter = document.getElementById('agents-type-filter');\n\n const searchText = searchInput ? searchInput.value.toLowerCase() : '';\n const typeValue = typeFilter ? typeFilter.value : '';\n\n return uniqueInstances.filter(instance => {\n // Search filter\n if (searchText) {\n const searchableText = [\n instance.agentName || '',\n instance.type || '',\n instance.isImplied ? 'implied' : 'explicit'\n ].join(' ').toLowerCase();\n\n if (!searchableText.includes(searchText)) {\n return false;\n }\n }\n\n // Type filter\n if (typeValue) {\n const agentName = instance.agentName || 'unknown';\n if (!agentName.toLowerCase().includes(typeValue.toLowerCase())) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n /**\n * Apply tools tab filtering\n * @param {Array} events - Events to filter\n * @returns {Array} - Filtered events\n */\n applyToolsFilters(events) {\n const searchInput = document.getElementById('tools-search-input');\n const typeFilter = document.getElementById('tools-type-filter');\n\n const searchText = searchInput ? searchInput.value.toLowerCase() : '';\n const typeValue = typeFilter ? typeFilter.value : '';\n\n return events.filter(event => {\n // Search filter\n if (searchText) {\n const searchableText = [\n event.tool_name || '',\n event.agent_type || '',\n event.type || '',\n event.subtype || ''\n ].join(' ').toLowerCase();\n\n if (!searchableText.includes(searchText)) {\n return false;\n }\n }\n\n // Type filter\n if (typeValue) {\n const toolName = event.tool_name || '';\n if (toolName !== typeValue) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n /**\n * Apply tools tab filtering for tool calls\n * @param {Array} toolCallsArray - Tool calls array to filter\n * @returns {Array} - Filtered tool calls\n */\n applyToolCallFilters(toolCallsArray) {\n const searchInput = document.getElementById('tools-search-input');\n const typeFilter = document.getElementById('tools-type-filter');\n\n const searchText = searchInput ? searchInput.value.toLowerCase() : '';\n const typeValue = typeFilter ? typeFilter.value : '';\n\n return toolCallsArray.filter(([key, toolCall]) => {\n // Search filter\n if (searchText) {\n const searchableText = [\n toolCall.tool_name || '',\n toolCall.agent_type || '',\n 'tool_call'\n ].join(' ').toLowerCase();\n\n if (!searchableText.includes(searchText)) {\n return false;\n }\n }\n\n // Type filter\n if (typeValue) {\n const toolName = toolCall.tool_name || '';\n if (toolName !== typeValue) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n /**\n * Apply files tab filtering\n * @param {Array} fileOperations - File operations to filter\n * @returns {Array} - Filtered file operations\n */\n applyFilesFilters(fileOperations) {\n const searchInput = document.getElementById('files-search-input');\n const typeFilter = document.getElementById('files-type-filter');\n\n const searchText = searchInput ? searchInput.value.toLowerCase() : '';\n const typeValue = typeFilter ? typeFilter.value : '';\n\n return fileOperations.filter(([filePath, fileData]) => {\n // Session filter - filter operations within each file\n if (this.selectedSessionId) {\n // Filter operations for this file by session\n const sessionOperations = fileData.operations.filter(op =>\n op.sessionId === this.selectedSessionId\n );\n\n // If no operations from this session, exclude the file\n if (sessionOperations.length === 0) {\n return false;\n }\n\n // Update the fileData to only include session-specific operations\n // (Note: This creates a filtered view without modifying the original)\n fileData = {\n ...fileData,\n operations: sessionOperations,\n lastOperation: sessionOperations[sessionOperations.length - 1]?.timestamp || fileData.lastOperation\n };\n }\n\n // Search filter\n if (searchText) {\n const searchableText = [\n filePath,\n ...fileData.operations.map(op => op.operation),\n ...fileData.operations.map(op => op.agent)\n ].join(' ').toLowerCase();\n\n if (!searchableText.includes(searchText)) {\n return false;\n }\n }\n\n // Type filter\n if (typeValue) {\n const operations = fileData.operations.map(op => op.operation);\n if (!operations.includes(typeValue)) {\n return false;\n }\n }\n\n return true;\n });\n }\n\n /**\n * Extract operation type from event type\n * @param {string} eventType - Event type string\n * @returns {string} - Operation type\n */\n extractOperation(eventType) {\n if (!eventType) return 'unknown';\n\n const type = eventType.toLowerCase();\n if (type.includes('read')) return 'read';\n if (type.includes('write')) return 'write';\n if (type.includes('edit')) return 'edit';\n if (type.includes('create')) return 'create';\n if (type.includes('delete')) return 'delete';\n if (type.includes('move') || type.includes('rename')) return 'move';\n\n return 'other';\n }\n\n /**\n * Extract tool name from hook event type\n * @param {string} eventType - Hook event type\n * @returns {string} - Tool name\n */\n extractToolFromHook(eventType) {\n if (!eventType) return '';\n\n // Pattern: Pre{ToolName}Use or Post{ToolName}Use\n const match = eventType.match(/^(?:Pre|Post)(.+)Use$/);\n return match ? match[1] : '';\n }\n\n /**\n * Extract tool name from subtype\n * @param {string} subtype - Event subtype\n * @returns {string} - Tool name\n */\n extractToolFromSubtype(subtype) {\n if (!subtype) return '';\n\n // Handle various subtype patterns\n if (subtype.includes('_')) {\n const parts = subtype.split('_');\n return parts[0] || '';\n }\n\n return subtype;\n }\n\n /**\n * Extract target information from tool parameters\n * @param {string} toolName - Tool name\n * @param {Object} params - Tool parameters\n * @param {Object} toolParameters - Alternative tool parameters\n * @returns {string} - Target information\n */\n extractToolTarget(toolName, params, toolParameters) {\n const parameters = params || toolParameters || {};\n\n switch (toolName?.toLowerCase()) {\n case 'read':\n case 'write':\n case 'edit':\n return parameters.file_path || parameters.path || '';\n case 'bash':\n return parameters.command || '';\n case 'grep':\n return parameters.pattern || '';\n case 'task':\n return parameters.subagent_type || parameters.agent_type || '';\n default:\n // Try to find a meaningful parameter\n const keys = Object.keys(parameters);\n const meaningfulKeys = ['path', 'file_path', 'command', 'pattern', 'query', 'target'];\n for (const key of meaningfulKeys) {\n if (parameters[key]) {\n return parameters[key];\n }\n }\n return keys.length > 0 ? `${keys[0]}: ${parameters[keys[0]]}` : '';\n }\n }\n\n /**\n * Generate HTML for unique agent instances (one row per PM delegation)\n * @param {Array} events - Agent events to render (not used, kept for compatibility)\n * @returns {string} - HTML string\n */\n generateAgentHTML(events) {\n // Get unique agent instances from agent inference\n const uniqueInstances = this.agentInference.getUniqueAgentInstances();\n\n // Apply filtering\n const filteredInstances = this.applyAgentsFilters(uniqueInstances);\n\n return filteredInstances.map((instance, index) => {\n const agentName = instance.agentName;\n const timestamp = this.formatTimestamp(instance.firstTimestamp || instance.timestamp);\n const delegationType = instance.isImplied ? 'implied' : 'explicit';\n // Fix: Use totalEventCount which is the actual property name from getUniqueAgentInstances()\n const eventCount = instance.totalEventCount || instance.eventCount || 0;\n\n const onclickString = `dashboard.selectCard('agents', ${index}, 'agent_instance', '${instance.id}'); dashboard.showAgentInstanceDetails('${instance.id}');`;\n\n // Format: \"[Agent Name] (delegationType, eventCount events)\" with separate timestamp\n const agentMainContent = `${agentName} (${delegationType}, ${eventCount} events)`;\n\n return `\n <div class=\"event-item single-row event-agent\" onclick=\"${onclickString}\">\n <span class=\"event-single-row-content\">\n <span class=\"event-content-main\">${agentMainContent}</span>\n <span class=\"event-timestamp\">${timestamp}</span>\n </span>\n </div>\n `;\n }).join('');\n }\n\n /**\n * Generate HTML for tool events\n * @param {Array} toolCalls - Tool calls to render\n * @returns {string} - HTML string\n */\n generateToolHTML(toolCalls) {\n const filteredToolCalls = this.applyToolCallFilters(toolCalls);\n\n return filteredToolCalls.map(([key, toolCall], index) => {\n const toolName = toolCall.tool_name || 'Unknown';\n const rawAgent = toolCall.agent_type || 'Unknown';\n const timestamp = this.formatTimestamp(toolCall.timestamp);\n const status = toolCall.post_event ? 'completed' : 'pending';\n const statusClass = status === 'completed' ? 'status-success' : 'status-pending';\n\n // Convert agent name: show \"pm\" for PM agent, otherwise show actual agent name\n const agentName = rawAgent.toLowerCase() === 'pm' ? 'pm' : rawAgent;\n\n // Format: \"Tool Name (Agent Name)\" - removed duration from main display\n const toolMainContent = `${toolName} (${agentName})`;\n\n return `\n <div class=\"event-item single-row event-tool ${statusClass}\" onclick=\"dashboard.selectCard('tools', ${index}, 'toolCall', '${key}'); dashboard.showToolCallDetails('${key}')\">\n <span class=\"event-single-row-content\">\n <span class=\"event-content-main\">${toolMainContent}</span>\n <span class=\"event-timestamp\">${timestamp}</span>\n </span>\n </div>\n `;\n }).join('');\n }\n\n /**\n * Generate HTML for file operations\n * @param {Array} fileOperations - File operations to render\n * @returns {string} - HTML string\n */\n generateFileHTML(fileOperations) {\n const filteredFiles = this.applyFilesFilters(fileOperations);\n\n return filteredFiles.map(([filePath, fileData], index) => {\n const operations = fileData.operations.map(op => op.operation);\n const timestamp = this.formatTimestamp(fileData.lastOperation);\n\n // Count operations by type for display: \"read(2), write(1)\"\n const operationCounts = {};\n operations.forEach(op => {\n operationCounts[op] = (operationCounts[op] || 0) + 1;\n });\n\n const operationSummary = Object.entries(operationCounts)\n .map(([op, count]) => `${op}(${count})`)\n .join(', ');\n\n // Get unique agents that worked on this file\n const uniqueAgents = [...new Set(fileData.operations.map(op => op.agent))];\n const agentSummary = uniqueAgents.length > 1 ? `by ${uniqueAgents.length} agents` : `by ${uniqueAgents[0] || 'unknown'}`;\n\n // Format: \"[file path] read(2), write(1) by agent\" with separate timestamp\n const fileName = this.getRelativeFilePath(filePath);\n const fileMainContent = `${fileName} ${operationSummary} ${agentSummary}`;\n\n return `\n <div class=\"event-item single-row file-item\" onclick=\"dashboard.selectCard('files', ${index}, 'file', '${filePath}'); dashboard.showFileDetails('${filePath}')\">\n <span class=\"event-single-row-content\">\n <span class=\"event-content-main\">${fileMainContent}</span>\n <span class=\"event-timestamp\">${timestamp}</span>\n </span>\n </div>\n `;\n }).join('');\n }\n\n /**\n * Get icon for file operations\n * @param {Array} operations - Array of operations\n * @returns {string} - Icon representation\n */\n getFileOperationIcon(operations) {\n if (operations.includes('write') || operations.includes('create')) return '📝';\n if (operations.includes('edit')) return '✏️';\n if (operations.includes('read')) return '👁️';\n if (operations.includes('delete')) return '🗑️';\n if (operations.includes('move')) return '📦';\n return '📄';\n }\n\n /**\n * Get relative file path\n * @param {string} filePath - Full file path\n * @returns {string} - Relative path\n */\n getRelativeFilePath(filePath) {\n if (!filePath) return '';\n\n // Simple relative path logic - can be enhanced\n const parts = filePath.split('/');\n if (parts.length > 3) {\n return '.../' + parts.slice(-2).join('/');\n }\n return filePath;\n }\n\n /**\n * Format timestamp for display\n * @param {string|number} timestamp - Timestamp to format\n * @returns {string} - Formatted timestamp\n */\n formatTimestamp(timestamp) {\n if (!timestamp) return '';\n\n const date = new Date(timestamp);\n return date.toLocaleTimeString();\n }\n\n /**\n * Set selected session ID for filtering\n * @param {string} sessionId - Session ID to filter by\n */\n setSelectedSessionId(sessionId) {\n this.selectedSessionId = sessionId;\n }\n\n /**\n * Get selected session ID\n * @returns {string|null} - Current session ID\n */\n getSelectedSessionId() {\n return this.selectedSessionId;\n }\n\n /**\n * Get unique tool instances (one row per unique tool call)\n * This deduplicates tool calls to show unique instances only\n * @param {Array} toolCallsArray - Tool calls array\n * @returns {Array} - Unique tool instances\n */\n getUniqueToolInstances(toolCallsArray) {\n // The toolCallsArray already represents unique tool calls\n // since it's generated from paired pre/post events in FileToolTracker\n // Just apply filtering and return\n return this.applyToolCallFilters(toolCallsArray);\n }\n\n /**\n * Get unique file instances (one row per unique file)\n * This aggregates all operations on each file\n * @param {Array} fileOperations - File operations array\n * @returns {Array} - Unique file instances (same as input since already unique per file)\n */\n getUniqueFileInstances(fileOperations) {\n // The fileOperations array already represents unique files\n // since it's keyed by file path in FileToolTracker\n // Just apply filtering and return\n return this.applyFilesFilters(fileOperations);\n }\n\n\n\n /**\n * Show agent instance details for unique instance view\n * @param {string} instanceId - Agent instance ID\n */\n showAgentInstanceDetails(instanceId) {\n const pmDelegations = this.agentInference.getPMDelegations();\n const instance = pmDelegations.get(instanceId);\n\n if (!instance) {\n console.error('Agent instance not found:', instanceId);\n return;\n }\n\n // Show details about this PM delegation and its events\n console.log('Showing agent instance details for:', instanceId, instance);\n\n // This would integrate with the existing detail view system\n // For now, just log the details - can be expanded to show in a modal/sidebar\n const detailsHtml = `\n <div class=\"agent-instance-details\">\n <h3>Agent Instance: ${instance.agentName}</h3>\n <p><strong>Type:</strong> ${instance.isImplied ? 'Implied PM Delegation' : 'Explicit PM Delegation'}</p>\n <p><strong>Start Time:</strong> ${this.formatTimestamp(instance.timestamp)}</p>\n <p><strong>Event Count:</strong> ${instance.agentEvents.length}</p>\n <p><strong>Session:</strong> ${instance.sessionId}</p>\n ${instance.pmCall ? `<p><strong>PM Call:</strong> Task delegation to ${instance.agentName}</p>` : '<p><strong>Note:</strong> Implied delegation (no explicit PM call found)</p>'}\n </div>\n `;\n\n // You would integrate this with your existing detail display system\n console.log('Agent instance details HTML:', detailsHtml);\n }\n}\n\n// ES6 Module export\nexport { EventProcessor };\nexport default EventProcessor;\n\n// Make EventProcessor globally available for dist/dashboard.js\nwindow.EventProcessor = EventProcessor;\n"],"names":["window","EventViewer","constructor","containerId","socketClient","this","container","document","getElementById","events","filteredEvents","selectedEventIndex","filteredEventElements","autoScroll","searchFilter","typeFilter","sessionFilter","eventTypeCount","availableEventTypes","Set","errorCount","eventsThisMinute","lastMinute","Date","getMinutes","init","setupEventHandlers","setupKeyboardNavigation","onEventUpdate","sessions","Array","isArray","updateDisplay","searchInput","addEventListener","e","target","value","toLowerCase","applyFilters","handleArrowNavigation","direction","length","newIndex","showEventDetails","console","warn","filter","event","type","subtype","JSON","stringify","data","join","includes","eventType","trim","session_id","renderEvents","updateMetrics","updateEventTypeDropdown","dropdown","eventTypes","forEach","fullType","add","currentTypes","from","sort","previousTypes","currentSelection","innerHTML","option","createElement","textContent","appendChild","has","eventsList","id","error","parentTab","closest","eventsTab","classList","contains","log","fileTreeTab","wasAtBottom","scrollTop","clientHeight","scrollHeight","html","map","index","timestamp","toLocaleTimeString","formatSingleRowEventContent","createInlineEditDiffViewer","querySelectorAll","dashboard","currentTab","tabNavigation","items","requestAnimationFrame","formatEventType","originalEventName","formatEventData","formatSessionEvent","formatClaudeEvent","formatAgentEvent","formatHookEvent","formatTodoEvent","formatMemoryEvent","formatLogEvent","formatCodeEvent","formatGenericEvent","prompt","message","substring","response","content","agent_type","name","event_type","prompt_text","prompt_preview","toolName","tool_name","operation_type","postToolName","success","status","duration_ms","notification_type","message_preview","reason","stop_type","startAgentType","agent","subagent_type","startPrompt","description","task","startTruncated","formatAgentType","agentType","stopReason","stop_reason","stopAgentDisplay","isCompleted","structured_response","task_completed","hookName","hook_name","todos","count","operation","key","level","truncated","toUpperCase","percentage","Math","round","path","duration","toFixed","file","nodes","nodes_count","node_type","json","agentTypeMap","research","architect","engineer","qa","pm","project_manager","research_agent","architect_agent","engineer_agent","qa_agent","unknown","lowerType","match","charAt","slice","sourcePrefix","source","dataDetails","hookType","agentDisplay","agentName","t","test_name","Object","keys","firstKey","find","k","getHookDisplayName","hookNames","pre_tool","post_tool","user_prompt","stop","subagent_start","subagent_stop","notification","String","replace","getEventCategory","selectedIndex","selectCard","el","i","toggle","dispatchEvent","CustomEvent","detail","selectedElement","scrollIntoView","behavior","block","clearSelection","remove","clearCardSelection","currentMinute","oneMinuteAgo","now","updateMetricsUI","totalEventsEl","eventsPerMinuteEl","uniqueTypesEl","errorCountEl","exportEvents","dataStr","dataBlob","Blob","url","URL","createObjectURL","link","href","download","toISOString","split","click","revokeObjectURL","clearEvents","setSessionFilter","sessionId","getFilters","search","session","getFilteredEvents","getAllEvents","edits","parameters","tool_parameters","old_string","new_string","push","file_path","edit","diffId","isMultiEdit","diffContent","editIndex","diffHtml","createDiffHtml","oldText","newText","oldLines","newLines","j","oldLine","newLine","escapeHtml","toggleEditDiff","stopPropagation","diffContainer","arrow","currentTarget","querySelector","isVisible","style","display","text","div","EventProcessor","eventViewer","agentInference","agentEvents","filteredAgentEvents","filteredToolEvents","filteredFileEvents","selectedSessionId","getFilteredEventsForTab","tabName","sessionManager","sessionEvents","getEventsForSession","applyAgentsFilters","uniqueInstances","searchText","typeValue","instance","isImplied","applyToolsFilters","applyToolCallFilters","toolCallsArray","toolCall","applyFilesFilters","fileOperations","filePath","fileData","sessionOperations","operations","op","lastOperation","extractOperation","extractToolFromHook","extractToolFromSubtype","extractToolTarget","params","toolParameters","command","pattern","meaningfulKeys","generateAgentHTML","getUniqueAgentInstances","formatTimestamp","firstTimestamp","delegationType","eventCount","totalEventCount","generateToolHTML","toolCalls","rawAgent","post_event","generateFileHTML","operationCounts","operationSummary","entries","uniqueAgents","agentSummary","getRelativeFilePath","getFileOperationIcon","parts","setSelectedSessionId","getSelectedSessionId","getUniqueToolInstances","getUniqueFileInstances","showAgentInstanceDetails","instanceId","getPMDelegations","get","detailsHtml","pmCall"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- window.ExportManager=class{constructor(e){this.eventViewer=e,this.setupEventHandlers(),console.log("Export manager initialized")}setupEventHandlers(){const e=document.querySelector('button[onclick="clearEvents()"]'),t=document.getElementById("export-btn");e&&e.addEventListener("click",()=>{this.clearEvents()}),t&&t.addEventListener("click",()=>{this.exportEvents()})}exportEvents(){this.eventViewer?this.eventViewer.exportEvents():console.error("Cannot export events: EventViewer not available")}clearEvents(){document.dispatchEvent(new CustomEvent("eventsClearing")),this.eventViewer&&this.eventViewer.clearEvents(),document.dispatchEvent(new CustomEvent("eventsCleared")),console.log("Events cleared")}exportEventsCustom(e={}){const{format:t="json",events:n=null,filename:o=null}=e,r=n||(this.eventViewer?this.eventViewer.events:[]);if(0===r.length)return void console.warn("No events to export");const i=(new Date).toISOString().replace(/[:.]/g,"-"),s=o||`claude-mpm-events-${i}`;let l="",a="",c="";switch(t.toLowerCase()){case"json":l=JSON.stringify(r,null,2),a="application/json",c=".json";break;case"csv":l=this.convertEventsToCSV(r),a="text/csv",c=".csv";break;case"txt":l=this.convertEventsToText(r),a="text/plain",c=".txt";break;default:return void console.error("Unsupported export format:",t)}this.downloadFile(l,s+c,a)}convertEventsToCSV(e){if(0===e.length)return"";return[["timestamp","type","subtype","tool_name","agent_type","session_id","data"],...e.map(e=>[e.timestamp||"",e.type||"",e.subtype||"",e.tool_name||"",e.agent_type||"",e.session_id||"",JSON.stringify(e.data||{}).replace(/"/g,'""')])].map(e=>e.map(e=>`"${e}"`).join(",")).join("\n")}convertEventsToText(e){return 0===e.length?"No events to export.":e.map((e,t)=>{const n=this.formatTimestamp(e.timestamp);let o=`Event ${t+1}: ${e.type||"Unknown"}${e.subtype?` (${e.subtype})`:""}${e.tool_name?` - Tool: ${e.tool_name}`:""}${e.agent_type?` - Agent: ${e.agent_type}`:""}\n`;return o+=` Time: ${n}\n`,o+=` Session: ${e.session_id||"Unknown"}\n`,e.data&&Object.keys(e.data).length>0&&(o+=` Data: ${JSON.stringify(e.data,null,2)}\n`),o}).join("\n"+"=".repeat(80)+"\n")}downloadFile(e,t,n){try{const o=new Blob([e],{type:n}),r=window.URL.createObjectURL(o),i=document.createElement("a");i.href=r,i.download=t,i.style.display="none",document.body.appendChild(i),i.click(),document.body.removeChild(i),window.URL.revokeObjectURL(r),console.log(`File exported: ${t}`)}catch(o){console.error("Failed to export file:",o)}}formatTimestamp(e){if(!e)return"Unknown time";try{const t=new Date(e);return isNaN(t.getTime())?"Invalid time":t.toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})}catch(t){return console.error("Error formatting timestamp:",t),"Error formatting time"}}formatFullTimestamp(e){if(!e)return"Unknown time";try{const t=new Date(e);return isNaN(t.getTime())?"Invalid time":t.toLocaleString("en-US",{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}catch(t){return console.error("Error formatting full timestamp:",t),"Error formatting time"}}scrollListToBottom(e){console.log(`[DEBUG] scrollListToBottom called with listId: ${e}`),setTimeout(()=>{const t=document.getElementById(e);console.log(`[DEBUG] Element found for ${e}:`,t),t?(console.log(`[DEBUG] Scrolling ${e} - scrollHeight: ${t.scrollHeight}, scrollTop before: ${t.scrollTop}`),t.scrollTop=t.scrollHeight,console.log(`[DEBUG] Scrolled ${e} - scrollTop after: ${t.scrollTop}`)):console.warn(`[DEBUG] Element with ID '${e}' not found for scrolling`)},50)}debounce(e,t){let n;return function(...o){clearTimeout(n),n=setTimeout(()=>{clearTimeout(n),e(...o)},t)}}throttle(e,t){let n;return function(...o){n||(e.apply(this,o),n=!0,setTimeout(()=>n=!1,t))}}generateId(){return Date.now().toString(36)+Math.random().toString(36).substr(2)}deepClone(e){if(null===e||"object"!=typeof e)return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(e=>this.deepClone(e));if("object"==typeof e){const t={};for(const n in e)e.hasOwnProperty(n)&&(t[n]=this.deepClone(e[n]));return t}return e}};
2
- //# sourceMappingURL=export-manager.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"export-manager.js","sources":["../../js/components/export-manager.js"],"sourcesContent":["/**\n * Export Manager Module\n *\n * Handles export functionality and utility functions for the dashboard.\n * Provides data export capabilities and common utility functions used across modules.\n *\n * WHY: Extracted from main dashboard to centralize export logic and utility functions\n * that don't belong to specific functional areas. This provides a clean place for\n * shared utilities while keeping export logic organized and testable.\n *\n * DESIGN DECISION: Combines export functionality with general utilities to avoid\n * creating too many small modules while keeping related functionality together.\n * Provides both data export and UI utility functions.\n */\nclass ExportManager {\n constructor(eventViewer) {\n this.eventViewer = eventViewer;\n this.setupEventHandlers();\n\n console.log('Export manager initialized');\n }\n\n /**\n * Set up event handlers for export functionality\n */\n setupEventHandlers() {\n const clearBtn = document.querySelector('button[onclick=\"clearEvents()\"]');\n const exportBtn = document.getElementById('export-btn');\n\n if (clearBtn) {\n clearBtn.addEventListener('click', () => {\n this.clearEvents();\n });\n }\n\n if (exportBtn) {\n exportBtn.addEventListener('click', () => {\n this.exportEvents();\n });\n }\n }\n\n /**\n * Export current events to file\n * Delegates to the event viewer's export functionality\n */\n exportEvents() {\n if (this.eventViewer) {\n this.eventViewer.exportEvents();\n } else {\n console.error('Cannot export events: EventViewer not available');\n }\n }\n\n /**\n * Clear all events and reset dashboard state\n * This is a coordinated clear that notifies all relevant modules\n */\n clearEvents() {\n // Dispatch event to notify other modules\n document.dispatchEvent(new CustomEvent('eventsClearing'));\n\n // Clear events from event viewer\n if (this.eventViewer) {\n this.eventViewer.clearEvents();\n }\n\n // Dispatch event to notify clearing is complete\n document.dispatchEvent(new CustomEvent('eventsCleared'));\n\n console.log('Events cleared');\n }\n\n /**\n * Export events with custom filtering\n * @param {Object} options - Export options\n * @param {string} options.format - Export format ('json', 'csv', 'txt')\n * @param {Array} options.events - Events to export (optional, uses all if not provided)\n * @param {string} options.filename - Custom filename (optional)\n */\n exportEventsCustom(options = {}) {\n const {\n format = 'json',\n events = null,\n filename = null\n } = options;\n\n const eventsToExport = events || (this.eventViewer ? this.eventViewer.events : []);\n\n if (eventsToExport.length === 0) {\n console.warn('No events to export');\n return;\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const defaultFilename = `claude-mpm-events-${timestamp}`;\n const exportFilename = filename || defaultFilename;\n\n let content = '';\n let mimeType = '';\n let fileExtension = '';\n\n switch (format.toLowerCase()) {\n case 'json':\n content = JSON.stringify(eventsToExport, null, 2);\n mimeType = 'application/json';\n fileExtension = '.json';\n break;\n\n case 'csv':\n content = this.convertEventsToCSV(eventsToExport);\n mimeType = 'text/csv';\n fileExtension = '.csv';\n break;\n\n case 'txt':\n content = this.convertEventsToText(eventsToExport);\n mimeType = 'text/plain';\n fileExtension = '.txt';\n break;\n\n default:\n console.error('Unsupported export format:', format);\n return;\n }\n\n this.downloadFile(content, exportFilename + fileExtension, mimeType);\n }\n\n /**\n * Convert events to CSV format\n * @param {Array} events - Events to convert\n * @returns {string} - CSV content\n */\n convertEventsToCSV(events) {\n if (events.length === 0) return '';\n\n // Define CSV headers\n const headers = ['timestamp', 'type', 'subtype', 'tool_name', 'agent_type', 'session_id', 'data'];\n\n // Convert events to CSV rows\n const rows = events.map(event => {\n return [\n event.timestamp || '',\n event.type || '',\n event.subtype || '',\n event.tool_name || '',\n event.agent_type || '',\n event.session_id || '',\n JSON.stringify(event.data || {}).replace(/\"/g, '\"\"') // Escape quotes for CSV\n ];\n });\n\n // Combine headers and rows\n const csvContent = [headers, ...rows]\n .map(row => row.map(field => `\"${field}\"`).join(','))\n .join('\\n');\n\n return csvContent;\n }\n\n /**\n * Convert events to readable text format\n * @param {Array} events - Events to convert\n * @returns {string} - Text content\n */\n convertEventsToText(events) {\n if (events.length === 0) return 'No events to export.';\n\n return events.map((event, index) => {\n const timestamp = this.formatTimestamp(event.timestamp);\n const type = event.type || 'Unknown';\n const subtype = event.subtype ? ` (${event.subtype})` : '';\n const toolName = event.tool_name ? ` - Tool: ${event.tool_name}` : '';\n const agentType = event.agent_type ? ` - Agent: ${event.agent_type}` : '';\n\n let content = `Event ${index + 1}: ${type}${subtype}${toolName}${agentType}\\n`;\n content += ` Time: ${timestamp}\\n`;\n content += ` Session: ${event.session_id || 'Unknown'}\\n`;\n\n if (event.data && Object.keys(event.data).length > 0) {\n content += ` Data: ${JSON.stringify(event.data, null, 2)}\\n`;\n }\n\n return content;\n }).join('\\n' + '='.repeat(80) + '\\n');\n }\n\n /**\n * Download file with given content\n * @param {string} content - File content\n * @param {string} filename - Filename\n * @param {string} mimeType - MIME type\n */\n downloadFile(content, filename, mimeType) {\n try {\n const blob = new Blob([content], { type: mimeType });\n const url = window.URL.createObjectURL(blob);\n\n const link = document.createElement('a');\n link.href = url;\n link.download = filename;\n link.style.display = 'none';\n\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n\n // Clean up the URL object\n window.URL.revokeObjectURL(url);\n\n console.log(`File exported: ${filename}`);\n } catch (error) {\n console.error('Failed to export file:', error);\n }\n }\n\n // =================\n // UTILITY FUNCTIONS\n // =================\n\n /**\n * Format timestamp for display\n * @param {string|number|Date} timestamp - Timestamp to format\n * @returns {string} - Formatted timestamp\n */\n formatTimestamp(timestamp) {\n if (!timestamp) return 'Unknown time';\n\n try {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) {\n return 'Invalid time';\n }\n\n return date.toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit'\n });\n } catch (error) {\n console.error('Error formatting timestamp:', error);\n return 'Error formatting time';\n }\n }\n\n /**\n * Format full timestamp with date for exports\n * @param {string|number|Date} timestamp - Timestamp to format\n * @returns {string} - Formatted full timestamp\n */\n formatFullTimestamp(timestamp) {\n if (!timestamp) return 'Unknown time';\n\n try {\n const date = new Date(timestamp);\n if (isNaN(date.getTime())) {\n return 'Invalid time';\n }\n\n return date.toLocaleString('en-US', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n hour12: false\n });\n } catch (error) {\n console.error('Error formatting full timestamp:', error);\n return 'Error formatting time';\n }\n }\n\n /**\n * Scroll a list element to bottom\n * @param {string} listId - ID of list element to scroll\n */\n scrollListToBottom(listId) {\n console.log(`[DEBUG] scrollListToBottom called with listId: ${listId}`);\n\n // Use setTimeout to ensure DOM updates are completed\n setTimeout(() => {\n const listElement = document.getElementById(listId);\n console.log(`[DEBUG] Element found for ${listId}:`, listElement);\n\n if (listElement) {\n console.log(`[DEBUG] Scrolling ${listId} - scrollHeight: ${listElement.scrollHeight}, scrollTop before: ${listElement.scrollTop}`);\n listElement.scrollTop = listElement.scrollHeight;\n console.log(`[DEBUG] Scrolled ${listId} - scrollTop after: ${listElement.scrollTop}`);\n } else {\n console.warn(`[DEBUG] Element with ID '${listId}' not found for scrolling`);\n }\n }, 50); // Small delay to ensure content is rendered\n }\n\n /**\n * Debounce function to limit function calls\n * @param {Function} func - Function to debounce\n * @param {number} wait - Wait time in milliseconds\n * @returns {Function} - Debounced function\n */\n debounce(func, wait) {\n let timeout;\n return function executedFunction(...args) {\n const later = () => {\n clearTimeout(timeout);\n func(...args);\n };\n clearTimeout(timeout);\n timeout = setTimeout(later, wait);\n };\n }\n\n /**\n * Throttle function to limit function calls\n * @param {Function} func - Function to throttle\n * @param {number} limit - Limit in milliseconds\n * @returns {Function} - Throttled function\n */\n throttle(func, limit) {\n let inThrottle;\n return function (...args) {\n if (!inThrottle) {\n func.apply(this, args);\n inThrottle = true;\n setTimeout(() => inThrottle = false, limit);\n }\n };\n }\n\n /**\n * Generate unique ID\n * @returns {string} - Unique ID\n */\n generateId() {\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\n }\n\n /**\n * Deep clone an object\n * @param {*} obj - Object to clone\n * @returns {*} - Cloned object\n */\n deepClone(obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n if (obj instanceof Date) return new Date(obj.getTime());\n if (obj instanceof Array) return obj.map(item => this.deepClone(item));\n if (typeof obj === 'object') {\n const cloned = {};\n for (const key in obj) {\n if (obj.hasOwnProperty(key)) {\n cloned[key] = this.deepClone(obj[key]);\n }\n }\n return cloned;\n }\n return obj;\n }\n}\n// ES6 Module export\nexport { ExportManager };\nexport default ExportManager;\n\n// Make ExportManager globally available for dist/dashboard.js\nwindow.ExportManager = ExportManager;\n"],"names":["window","ExportManager","constructor","eventViewer","this","setupEventHandlers","console","log","clearBtn","document","querySelector","exportBtn","getElementById","addEventListener","clearEvents","exportEvents","error","dispatchEvent","CustomEvent","exportEventsCustom","options","format","events","filename","eventsToExport","length","warn","timestamp","Date","toISOString","replace","exportFilename","content","mimeType","fileExtension","toLowerCase","JSON","stringify","convertEventsToCSV","convertEventsToText","downloadFile","map","event","type","subtype","tool_name","agent_type","session_id","data","row","field","join","index","formatTimestamp","Object","keys","repeat","blob","Blob","url","URL","createObjectURL","link","createElement","href","download","style","display","body","appendChild","click","removeChild","revokeObjectURL","date","isNaN","getTime","toLocaleTimeString","hour12","hour","minute","second","formatFullTimestamp","toLocaleString","year","month","day","scrollListToBottom","listId","setTimeout","listElement","scrollHeight","scrollTop","debounce","func","wait","timeout","args","clearTimeout","throttle","limit","inThrottle","apply","generateId","now","toString","Math","random","substr","deepClone","obj","Array","item","cloned","key","hasOwnProperty"],"mappings":"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"}