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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +12 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +1055 -2230
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
- claude_mpm/agents/WORKFLOW.md +4 -4
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +576 -66
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +28 -3
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +188 -30
- claude_mpm/cli/commands/agents.py +959 -36
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/auto_configure.py +537 -239
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +924 -45
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +1 -39
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +322 -19
- claude_mpm/cli/executor.py +22 -3
- claude_mpm/cli/interactive/agent_wizard.py +1028 -43
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +256 -4
- claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
- claude_mpm/cli/parsers/base_parser.py +25 -0
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +7 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +456 -103
- claude_mpm/cli/startup_display.py +4 -4
- claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
- claude_mpm/commands/mpm-agents-detect.md +9 -0
- claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
- claude_mpm/commands/mpm-agents-recommend.md +9 -0
- claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +14 -2
- claude_mpm/commands/mpm-init.md +9 -0
- claude_mpm/commands/mpm-monitor.md +9 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
- claude_mpm/commands/mpm-status.md +9 -0
- claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +9 -0
- claude_mpm/commands/mpm.md +10 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +5 -34
- claude_mpm/core/config.py +16 -0
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
- claude_mpm/core/interactive_session.py +83 -7
- claude_mpm/core/oneshot_session.py +71 -8
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/unified_config.py +22 -0
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/services/agents/agent_builder.py +45 -9
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +1 -4
- claude_mpm/services/agents/local_template_manager.py +47 -9
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/command_deployment_service.py +200 -6
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +34 -6
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/monitor/daemon.py +28 -8
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/project_organizer.py +4 -0
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/templates/questions/__init__.py +2 -7
- claude_mpm/templates/questions/pr_strategy.py +1 -4
- claude_mpm/templates/questions/project_init.py +1 -4
- claude_mpm/templates/questions/ticket_mgmt.py +1 -4
- claude_mpm/utils/agent_dependency_loader.py +77 -10
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/gitignore.py +3 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +356 -112
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +188 -439
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -183
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -238
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -144
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -243
- claude_mpm/agents/templates/react_engineer.json +0 -239
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -258
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/tauri_engineer.json +0 -274
- claude_mpm/agents/templates/ticketing.json +0 -181
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -159
- claude_mpm/agents/templates/web_qa.json +0 -400
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/cli/README.md +0 -253
- claude_mpm/cli/commands/mcp_install_commands.py.backup +0 -284
- claude_mpm/cli/commands/mpm_init/README.md +0 -365
- claude_mpm/cli_module/refactoring_guide.md +0 -253
- claude_mpm/commands/mpm-tickets.md +0 -151
- claude_mpm/config/agent_capabilities.yaml +0 -658
- claude_mpm/config/async_logging_config.yaml +0 -145
- claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
- claude_mpm/d2/.gitignore +0 -22
- claude_mpm/d2/ARCHITECTURE_COMPARISON.md +0 -273
- claude_mpm/d2/FLASK_INTEGRATION.md +0 -156
- claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +0 -452
- claude_mpm/d2/QUICKSTART.md +0 -186
- claude_mpm/d2/README.md +0 -232
- claude_mpm/d2/STORE_FIX_SUMMARY.md +0 -167
- claude_mpm/d2/SVELTE5_STORES_GUIDE.md +0 -180
- claude_mpm/d2/TESTING.md +0 -288
- claude_mpm/d2/index.html +0 -118
- claude_mpm/d2/package.json +0 -19
- claude_mpm/d2/src/App.svelte +0 -110
- claude_mpm/d2/src/components/Header.svelte +0 -153
- claude_mpm/d2/src/components/MainContent.svelte +0 -74
- claude_mpm/d2/src/components/Sidebar.svelte +0 -85
- claude_mpm/d2/src/components/tabs/EventsTab.svelte +0 -326
- claude_mpm/d2/src/lib/socketio.js +0 -144
- claude_mpm/d2/src/main.js +0 -7
- claude_mpm/d2/src/stores/events.js +0 -114
- claude_mpm/d2/src/stores/socket.js +0 -108
- claude_mpm/d2/src/stores/theme.js +0 -65
- claude_mpm/d2/svelte.config.js +0 -12
- claude_mpm/d2/vite.config.js +0 -15
- claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/BUILD_NUMBER +0 -1
- claude_mpm/dashboard/README.md +0 -121
- claude_mpm/dashboard/VERSION +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +0 -273
- claude_mpm/dashboard/react/components/ErrorBoundary.tsx +0 -75
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +0 -141
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +0 -36
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/react/components/shared/FilterBar.tsx +0 -89
- claude_mpm/dashboard/react/contexts/DashboardContext.tsx +0 -215
- claude_mpm/dashboard/react/entries/events.tsx +0 -165
- claude_mpm/dashboard/react/hooks/useEvents.ts +0 -191
- claude_mpm/dashboard/react/hooks/useSocket.ts +0 -225
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +0 -170
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/activity-tree.js.map +0 -1
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-inference.js.map +0 -1
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-tree.js.map +0 -1
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-processor.js.map +0 -1
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +0 -1
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/session-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +0 -1
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +0 -1
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js.map +0 -1
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/dashboard.js.map +0 -1
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/react/events.js.map +0 -1
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/socket-client.js.map +0 -1
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +0 -170
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/navigation-test-results.md +0 -118
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
- claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
- claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
- claude_mpm/hooks/README.md +0 -143
- claude_mpm/hooks/templates/README.md +0 -180
- claude_mpm/hooks/templates/settings.json.example +0 -147
- claude_mpm/schemas/agent_schema.json +0 -596
- claude_mpm/schemas/frontmatter_schema.json +0 -165
- claude_mpm/services/event_bus/README.md +0 -244
- claude_mpm/services/events/README.md +0 -303
- claude_mpm/services/framework_claude_md_generator/README.md +0 -119
- claude_mpm/services/mcp_gateway/README.md +0 -185
- claude_mpm/services/socketio/handlers/connection.py.backup +0 -217
- claude_mpm/services/socketio/handlers/hook.py.backup +0 -154
- claude_mpm/services/static/.gitkeep +0 -2
- claude_mpm/services/version_control/VERSION +0 -1
- claude_mpm/skills/bundled/.gitkeep +0 -2
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +0 -317
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +0 -251
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +0 -63
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +0 -611
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +0 -596
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +0 -260
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +0 -315
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +0 -436
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +0 -433
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +0 -452
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +0 -404
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +0 -420
- claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +0 -54
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +0 -322
- claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +0 -22
- claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +0 -2
- claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/react/flexlayout-react.md +0 -742
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +0 -495
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +0 -599
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +0 -535
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +0 -613
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +0 -648
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +0 -673
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +0 -767
- claude_mpm/skills/bundled/tauri/tauri-performance.md +0 -669
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +0 -573
- claude_mpm/skills/bundled/tauri/tauri-testing.md +0 -384
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +0 -628
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +0 -158
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +0 -458
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +0 -411
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +0 -317
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +0 -270
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +0 -436
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +0 -202
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- claude_mpm/templates/questions/EXAMPLES.md +0 -501
- claude_mpm/tools/README_SOCKETIO_DEBUG.md +0 -224
- claude_mpm/tools/code_tree_analyzer/README.md +0 -64
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
|
@@ -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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"}
|