claude-mpm 4.20.3__py3-none-any.whl โ†’ 4.25.10__py3-none-any.whl

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

Potentially problematic release.


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

Files changed (454) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +23 -6
  3. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  4. claude_mpm/agents/PM_INSTRUCTIONS.md +1783 -34
  5. claude_mpm/agents/WORKFLOW.md +75 -2
  6. claude_mpm/agents/base_agent.json +6 -3
  7. claude_mpm/agents/frontmatter_validator.py +1 -1
  8. claude_mpm/agents/templates/api_qa.json +5 -2
  9. claude_mpm/agents/templates/circuit_breakers.md +108 -2
  10. claude_mpm/agents/templates/documentation.json +33 -6
  11. claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
  12. claude_mpm/agents/templates/php-engineer.json +10 -4
  13. claude_mpm/agents/templates/pm_red_flags.md +89 -19
  14. claude_mpm/agents/templates/project_organizer.json +7 -3
  15. claude_mpm/agents/templates/qa.json +2 -1
  16. claude_mpm/agents/templates/react_engineer.json +1 -0
  17. claude_mpm/agents/templates/research.json +82 -12
  18. claude_mpm/agents/templates/security.json +4 -4
  19. claude_mpm/agents/templates/tauri_engineer.json +274 -0
  20. claude_mpm/agents/templates/ticketing.json +10 -6
  21. claude_mpm/agents/templates/version_control.json +4 -2
  22. claude_mpm/agents/templates/web_qa.json +2 -1
  23. claude_mpm/cli/README.md +253 -0
  24. claude_mpm/cli/__init__.py +11 -1
  25. claude_mpm/cli/commands/aggregate.py +1 -1
  26. claude_mpm/cli/commands/analyze.py +3 -3
  27. claude_mpm/cli/commands/cleanup.py +1 -1
  28. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  29. claude_mpm/cli/commands/debug.py +12 -12
  30. claude_mpm/cli/commands/hook_errors.py +277 -0
  31. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  32. claude_mpm/cli/commands/mcp_install_commands.py.backup +284 -0
  33. claude_mpm/cli/commands/mpm_init/README.md +365 -0
  34. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  35. claude_mpm/cli/commands/mpm_init/core.py +573 -0
  36. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  37. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  38. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  39. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  40. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  41. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  42. claude_mpm/cli/commands/run.py +124 -128
  43. claude_mpm/cli/commands/skills.py +522 -34
  44. claude_mpm/cli/executor.py +56 -0
  45. claude_mpm/cli/interactive/agent_wizard.py +5 -5
  46. claude_mpm/cli/parsers/base_parser.py +28 -0
  47. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  48. claude_mpm/cli/parsers/skills_parser.py +138 -0
  49. claude_mpm/cli/startup.py +111 -8
  50. claude_mpm/cli/startup_display.py +480 -0
  51. claude_mpm/cli/utils.py +1 -1
  52. claude_mpm/cli_module/commands.py +1 -1
  53. claude_mpm/cli_module/refactoring_guide.md +253 -0
  54. claude_mpm/commands/mpm-help.md +3 -0
  55. claude_mpm/commands/mpm-init.md +19 -3
  56. claude_mpm/commands/mpm-resume.md +372 -0
  57. claude_mpm/commands/mpm-tickets.md +56 -7
  58. claude_mpm/commands/mpm.md +1 -0
  59. claude_mpm/config/agent_capabilities.yaml +658 -0
  60. claude_mpm/config/async_logging_config.yaml +145 -0
  61. claude_mpm/constants.py +12 -0
  62. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +34 -0
  63. claude_mpm/core/api_validator.py +1 -1
  64. claude_mpm/core/claude_runner.py +14 -1
  65. claude_mpm/core/config.py +8 -0
  66. claude_mpm/core/constants.py +1 -1
  67. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  68. claude_mpm/core/hook_error_memory.py +381 -0
  69. claude_mpm/core/hook_manager.py +41 -2
  70. claude_mpm/core/interactive_session.py +48 -3
  71. claude_mpm/core/interfaces.py +56 -1
  72. claude_mpm/core/logger.py +3 -1
  73. claude_mpm/core/oneshot_session.py +39 -0
  74. claude_mpm/d2/.gitignore +22 -0
  75. claude_mpm/d2/ARCHITECTURE_COMPARISON.md +273 -0
  76. claude_mpm/d2/FLASK_INTEGRATION.md +156 -0
  77. claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +452 -0
  78. claude_mpm/d2/QUICKSTART.md +186 -0
  79. claude_mpm/d2/README.md +232 -0
  80. claude_mpm/d2/STORE_FIX_SUMMARY.md +167 -0
  81. claude_mpm/d2/SVELTE5_STORES_GUIDE.md +180 -0
  82. claude_mpm/d2/TESTING.md +288 -0
  83. claude_mpm/d2/index.html +118 -0
  84. claude_mpm/d2/package.json +19 -0
  85. claude_mpm/d2/src/App.svelte +110 -0
  86. claude_mpm/d2/src/components/Header.svelte +153 -0
  87. claude_mpm/d2/src/components/MainContent.svelte +74 -0
  88. claude_mpm/d2/src/components/Sidebar.svelte +85 -0
  89. claude_mpm/d2/src/components/tabs/EventsTab.svelte +326 -0
  90. claude_mpm/d2/src/lib/socketio.js +144 -0
  91. claude_mpm/d2/src/main.js +7 -0
  92. claude_mpm/d2/src/stores/events.js +114 -0
  93. claude_mpm/d2/src/stores/socket.js +108 -0
  94. claude_mpm/d2/src/stores/theme.js +65 -0
  95. claude_mpm/d2/svelte.config.js +12 -0
  96. claude_mpm/d2/vite.config.js +15 -0
  97. claude_mpm/dashboard/.claude-mpm/memories/README.md +36 -0
  98. claude_mpm/dashboard/BUILD_NUMBER +1 -0
  99. claude_mpm/dashboard/README.md +121 -0
  100. claude_mpm/dashboard/VERSION +1 -0
  101. claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +273 -0
  102. claude_mpm/dashboard/react/components/ErrorBoundary.tsx +75 -0
  103. claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +141 -0
  104. claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +36 -0
  105. claude_mpm/dashboard/react/components/shared/FilterBar.tsx +89 -0
  106. claude_mpm/dashboard/react/contexts/DashboardContext.tsx +215 -0
  107. claude_mpm/dashboard/react/entries/events.tsx +165 -0
  108. claude_mpm/dashboard/react/hooks/useEvents.ts +191 -0
  109. claude_mpm/dashboard/react/hooks/useSocket.ts +225 -0
  110. claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +170 -0
  111. claude_mpm/dashboard/static/built/components/activity-tree.js.map +1 -0
  112. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +101 -101
  113. claude_mpm/dashboard/static/built/components/agent-inference.js.map +1 -0
  114. claude_mpm/dashboard/static/built/components/build-tracker.js +59 -59
  115. claude_mpm/dashboard/static/built/components/code-simple.js +107 -107
  116. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +29 -29
  117. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +24 -24
  118. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +27 -27
  119. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +25 -25
  120. claude_mpm/dashboard/static/built/components/code-tree.js.map +1 -0
  121. claude_mpm/dashboard/static/built/components/code-viewer.js.map +1 -0
  122. claude_mpm/dashboard/static/built/components/connection-debug.js +101 -101
  123. claude_mpm/dashboard/static/built/components/diff-viewer.js +113 -113
  124. claude_mpm/dashboard/static/built/components/event-processor.js.map +1 -0
  125. claude_mpm/dashboard/static/built/components/event-viewer.js.map +1 -0
  126. claude_mpm/dashboard/static/built/components/export-manager.js.map +1 -0
  127. claude_mpm/dashboard/static/built/components/file-change-tracker.js +57 -57
  128. claude_mpm/dashboard/static/built/components/file-change-viewer.js +74 -74
  129. claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +1 -0
  130. claude_mpm/dashboard/static/built/components/file-viewer.js.map +1 -0
  131. claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +1 -0
  132. claude_mpm/dashboard/static/built/components/hud-manager.js.map +1 -0
  133. claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +1 -0
  134. claude_mpm/dashboard/static/built/components/module-viewer.js.map +1 -0
  135. claude_mpm/dashboard/static/built/components/session-manager.js.map +1 -0
  136. claude_mpm/dashboard/static/built/components/socket-manager.js.map +1 -0
  137. claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +1 -0
  138. claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +1 -0
  139. claude_mpm/dashboard/static/built/components/working-directory.js.map +1 -0
  140. claude_mpm/dashboard/static/built/connection-manager.js +76 -76
  141. claude_mpm/dashboard/static/built/dashboard.js.map +1 -0
  142. claude_mpm/dashboard/static/built/extension-error-handler.js +22 -22
  143. claude_mpm/dashboard/static/built/react/events.js.map +1 -0
  144. claude_mpm/dashboard/static/built/shared/dom-helpers.js +9 -9
  145. claude_mpm/dashboard/static/built/shared/event-bus.js +5 -5
  146. claude_mpm/dashboard/static/built/shared/logger.js +16 -16
  147. claude_mpm/dashboard/static/built/shared/tooltip-service.js +6 -6
  148. claude_mpm/dashboard/static/built/socket-client.js.map +1 -0
  149. claude_mpm/dashboard/static/css/activity.css +69 -69
  150. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  151. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  152. claude_mpm/dashboard/static/index.html +22 -22
  153. claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +170 -0
  154. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  155. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  156. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  157. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  158. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  159. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  160. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  161. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  162. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  163. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  164. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  165. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  166. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  167. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  168. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  169. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  170. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  171. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  172. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  173. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  174. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  175. claude_mpm/dashboard/static/js/shared/dom-helpers.js +9 -9
  176. claude_mpm/dashboard/static/js/shared/event-bus.js +5 -5
  177. claude_mpm/dashboard/static/js/shared/logger.js +16 -16
  178. claude_mpm/dashboard/static/js/shared/tooltip-service.js +6 -6
  179. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  180. claude_mpm/dashboard/static/navigation-test-results.md +118 -0
  181. claude_mpm/dashboard/static/production/main.html +21 -21
  182. claude_mpm/dashboard/static/test-archive/dashboard.html +22 -22
  183. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +36 -0
  184. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +39 -0
  185. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +38 -0
  186. claude_mpm/dashboard/templates/code_simple.html +23 -23
  187. claude_mpm/dashboard/templates/index.html +18 -18
  188. claude_mpm/hooks/README.md +143 -0
  189. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  190. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  191. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  192. claude_mpm/hooks/templates/README.md +180 -0
  193. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  194. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  195. claude_mpm/hooks/templates/settings.json.example +147 -0
  196. claude_mpm/schemas/agent_schema.json +596 -0
  197. claude_mpm/schemas/frontmatter_schema.json +165 -0
  198. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  199. claude_mpm/scripts/start_activity_logging.py +3 -1
  200. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  201. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  202. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  203. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  204. claude_mpm/services/agents/loading/framework_agent_loader.py +8 -8
  205. claude_mpm/services/agents/local_template_manager.py +3 -1
  206. claude_mpm/services/cli/session_pause_manager.py +504 -0
  207. claude_mpm/services/cli/session_resume_helper.py +36 -16
  208. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  209. claude_mpm/services/core/base.py +26 -11
  210. claude_mpm/services/core/interfaces.py +56 -1
  211. claude_mpm/services/core/models/agent_config.py +3 -0
  212. claude_mpm/services/core/models/process.py +4 -0
  213. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  214. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  215. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  216. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  217. claude_mpm/services/diagnostics/doctor_reporter.py +6 -4
  218. claude_mpm/services/diagnostics/models.py +21 -0
  219. claude_mpm/services/event_bus/README.md +244 -0
  220. claude_mpm/services/event_bus/direct_relay.py +3 -3
  221. claude_mpm/services/event_bus/event_bus.py +36 -3
  222. claude_mpm/services/event_bus/relay.py +23 -7
  223. claude_mpm/services/events/README.md +303 -0
  224. claude_mpm/services/events/consumers/logging.py +1 -2
  225. claude_mpm/services/framework_claude_md_generator/README.md +119 -0
  226. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  227. claude_mpm/services/local_ops/__init__.py +2 -0
  228. claude_mpm/services/local_ops/process_manager.py +1 -1
  229. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  230. claude_mpm/services/mcp_gateway/README.md +185 -0
  231. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  232. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  233. claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
  234. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  235. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  236. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  237. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  238. claude_mpm/services/memory/failure_tracker.py +19 -4
  239. claude_mpm/services/memory/optimizer.py +1 -1
  240. claude_mpm/services/model/model_router.py +8 -9
  241. claude_mpm/services/monitor/daemon.py +1 -1
  242. claude_mpm/services/monitor/server.py +2 -2
  243. claude_mpm/services/native_agent_converter.py +356 -0
  244. claude_mpm/services/port_manager.py +1 -1
  245. claude_mpm/services/project/documentation_manager.py +2 -1
  246. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  247. claude_mpm/services/runner_configuration_service.py +1 -0
  248. claude_mpm/services/self_upgrade_service.py +165 -7
  249. claude_mpm/services/skills_config.py +547 -0
  250. claude_mpm/services/skills_deployer.py +955 -0
  251. claude_mpm/services/socketio/handlers/connection.py +1 -1
  252. claude_mpm/services/socketio/handlers/connection.py.backup +217 -0
  253. claude_mpm/services/socketio/handlers/git.py +2 -2
  254. claude_mpm/services/socketio/handlers/hook.py.backup +154 -0
  255. claude_mpm/services/static/.gitkeep +2 -0
  256. claude_mpm/services/system_instructions_service.py +1 -3
  257. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  258. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  259. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  260. claude_mpm/services/version_control/VERSION +1 -0
  261. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  262. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  263. claude_mpm/skills/__init__.py +3 -3
  264. claude_mpm/skills/agent_skills_injector.py +42 -49
  265. claude_mpm/skills/bundled/.gitkeep +2 -0
  266. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +4 -0
  267. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +108 -114
  268. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  269. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  270. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  271. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  272. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  273. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +46 -41
  274. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  275. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  276. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +36 -73
  277. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  278. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  279. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +100 -125
  280. claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +63 -0
  281. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  282. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  283. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  284. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  285. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +28 -72
  286. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +11 -0
  287. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  288. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  289. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +272 -0
  290. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  291. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  292. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  293. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  294. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  295. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  296. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  297. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  298. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  299. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  300. claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +202 -0
  301. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +13 -1
  302. claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +54 -0
  303. claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +322 -0
  304. claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  305. claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +202 -0
  306. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +11 -0
  307. claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +202 -0
  308. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +109 -277
  309. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  310. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  311. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +17 -10
  312. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +92 -39
  313. claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +22 -0
  314. claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +2 -0
  315. claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +202 -0
  316. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +135 -155
  317. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  318. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  319. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  320. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  321. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  322. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +13 -12
  323. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +5 -3
  324. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +19 -12
  325. claude_mpm/skills/bundled/performance-profiling.md +6 -0
  326. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  327. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  328. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  329. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  330. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  331. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  332. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  333. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  334. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  335. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  336. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  337. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  338. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  339. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  340. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  341. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  342. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  343. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  344. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  345. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  346. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  347. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  348. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  349. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  350. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  351. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  352. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +21 -25
  353. claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +158 -0
  354. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  355. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  356. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  357. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  358. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  359. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  360. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +86 -250
  361. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  362. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  363. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  364. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  365. claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +202 -0
  366. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +145 -57
  367. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  368. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +6 -6
  369. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +13 -9
  370. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +8 -8
  371. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  372. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  373. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +37 -15
  374. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  375. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  376. claude_mpm/skills/skills_registry.py +44 -48
  377. claude_mpm/skills/skills_service.py +117 -108
  378. claude_mpm/templates/questions/EXAMPLES.md +501 -0
  379. claude_mpm/templates/questions/__init__.py +43 -0
  380. claude_mpm/templates/questions/base.py +193 -0
  381. claude_mpm/templates/questions/pr_strategy.py +314 -0
  382. claude_mpm/templates/questions/project_init.py +388 -0
  383. claude_mpm/templates/questions/ticket_mgmt.py +397 -0
  384. claude_mpm/tools/README_SOCKETIO_DEBUG.md +224 -0
  385. claude_mpm/tools/__main__.py +8 -8
  386. claude_mpm/tools/code_tree_analyzer/README.md +64 -0
  387. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  388. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  389. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  390. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  391. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  392. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  393. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  394. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  395. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  396. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  397. claude_mpm/utils/agent_dependency_loader.py +3 -3
  398. claude_mpm/utils/dependency_cache.py +3 -1
  399. claude_mpm/utils/gitignore.py +241 -0
  400. claude_mpm/utils/log_cleanup.py +3 -3
  401. claude_mpm/utils/robust_installer.py +3 -5
  402. claude_mpm/utils/structured_questions.py +619 -0
  403. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/METADATA +218 -31
  404. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/RECORD +409 -246
  405. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  406. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  407. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  408. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  409. claude_mpm/cli/commands/mpm_init.py +0 -2093
  410. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  411. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  412. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  413. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  414. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  415. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  416. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  417. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  418. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  419. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  420. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  421. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  422. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  423. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  424. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  425. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  426. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  427. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  428. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  429. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  430. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  431. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  432. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  433. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  434. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  435. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  436. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  437. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  438. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  439. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  440. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  441. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  442. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  443. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  444. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  445. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  446. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  447. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  448. claude_mpm/skills/bundled/debugging/verification-before-completion/references/common-failures.md +0 -213
  449. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  450. /claude_mpm/skills/bundled/collaboration/requesting-code-review/{code-reviewer.md โ†’ references/code-reviewer-template.md} +0 -0
  451. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/WHEEL +0 -0
  452. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/entry_points.txt +0 -0
  453. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/licenses/LICENSE +0 -0
  454. {claude_mpm-4.20.3.dist-info โ†’ claude_mpm-4.25.10.dist-info}/top_level.txt +0 -0
@@ -1,2 +0,0 @@
1
- import{U as t}from"./unified-data-viewer.js";window.ModuleViewer=class{constructor(e){this.container=document.getElementById(e),this.dataContainer=null,this.jsonContainer=null,this.currentEvent=null,this.eventsByClass=new Map,this.globalJsonExpanded="true"===localStorage.getItem("dashboard-json-expanded"),this.fullEventDataExpanded="true"===localStorage.getItem("dashboard-full-event-expanded"),this.keyboardListenerAdded=!1,this.unifiedViewer=new t("module-data-content"),this.unifiedViewer.globalJsonExpanded=this.globalJsonExpanded,this.unifiedViewer.fullEventDataExpanded=this.fullEventDataExpanded,document.addEventListener("jsonToggleChanged",t=>{this.globalJsonExpanded=t.detail.expanded,this.unifiedViewer.globalJsonExpanded!==t.detail.expanded&&(this.unifiedViewer.globalJsonExpanded=t.detail.expanded)}),document.addEventListener("fullEventToggleChanged",t=>{this.fullEventDataExpanded=t.detail.expanded,this.unifiedViewer.fullEventDataExpanded!==t.detail.expanded&&(this.unifiedViewer.fullEventDataExpanded=t.detail.expanded)}),this.init()}init(){this.setupContainers(),this.setupEventHandlers(),this.showEmptyState()}setupContainers(){this.dataContainer=document.getElementById("module-data-content"),this.jsonContainer=null,this.dataContainer||console.error("Module viewer data container not found")}setupEventHandlers(){document.addEventListener("eventSelected",t=>{this.showEventDetails(t.detail.event)}),document.addEventListener("eventSelectionCleared",()=>{this.showEmptyState()}),document.addEventListener("socketEventUpdate",t=>{this.updateEventsByClass(t.detail.events)})}showEmptyState(){this.dataContainer&&(this.dataContainer.innerHTML='\n <div class="module-empty">\n <p>Click on an event to view structured data</p>\n <p class="module-hint">Data is organized by event type</p>\n </div>\n '),this.currentEvent=null}showEventDetails(t){if(this.currentEvent=t,!this.unifiedViewer)return console.warn("ModuleViewer: UnifiedDataViewer not available"),this.renderStructuredData(t),void this.renderJsonData(t);this.unifiedViewer.display(t,"event")}renderStructuredData(t){if(!this.dataContainer)return;const e=this.createContextualHeader(t),n=this.createEventStructuredView(t),s=this.createCollapsibleJsonSection(t);this.dataContainer.innerHTML=e+n+s,this.initializeJsonToggle()}renderJsonData(t){}ingest(t){Array.isArray(t)?t.length>0?this.showEventDetails(t[0]):this.showEmptyState():t&&"object"==typeof t?this.showEventDetails(t):this.showEmptyState()}updateEventsByClass(t){this.eventsByClass.clear(),t.forEach(t=>{const e=this.getEventClass(t);this.eventsByClass.has(e)||this.eventsByClass.set(e,[]),this.eventsByClass.get(e).push(t)})}getEventClass(t){if(!t.type)return"unknown";switch(t.type){case"session":return"Session Management";case"claude":return"Claude Interactions";case"agent":return"Agent Operations";case"hook":return"Hook System";case"todo":return"Task Management";case"memory":return"Memory Operations";case"log":return"System Logs";case"connection":return"Connection Events";default:return"Other Events"}}createContextualHeader(t){const e=this.formatTimestamp(t.timestamp),n=t.data||{};let s="";switch(t.type){case"hook":const o=this.extractToolName(n),a=this.extractAgent(t)||"Unknown";if(o)s=`${o}: ${a} ${e}`;else{s=`${this.getHookDisplayName(t,n)}: ${a} ${e}`}break;case"agent":s=`Agent: ${n.agent_type||n.name||"Unknown"} ${e}`;break;case"todo":s=`TodoWrite: ${this.extractAgent(t)||"PM"} ${e}`;break;case"memory":s=`Memory: ${n.operation||"Unknown"} ${e}`;break;case"session":case"claude":case"log":case"connection":s=`Event: ${t.type}.${t.subtype||"default"} ${e}`;break;default:const i=this.extractFileName(n);if(i)s=`File: ${i} ${e}`;else{s=`Event: ${t.type||"Unknown"}.${t.subtype||"default"} ${e}`}}return`\n <div class="contextual-header">\n <h3 class="contextual-header-text">${s}</h3>\n </div>\n `}createEventStructuredView(t){const e=this.getEventClass(t),n=(this.eventsByClass.get(e)||[]).length;let s=`\n <div class="structured-view-section">\n ${this.createEventDetailCard(t.type,t,n)}\n </div>\n `;switch(t.type){case"agent":s+=this.createAgentStructuredView(t);break;case"hook":"Task"===t.data?.tool_name&&t.data?.tool_parameters?.subagent_type?s+=this.createAgentStructuredView(t):s+=this.createHookStructuredView(t);break;case"todo":s+=this.createTodoStructuredView(t);break;case"memory":s+=this.createMemoryStructuredView(t);break;case"claude":s+=this.createClaudeStructuredView(t);break;case"session":s+=this.createSessionStructuredView(t);break;default:s+=this.createGenericStructuredView(t)}return s}createEventDetailCard(t,e,n){const s=new Date(e.timestamp).toLocaleString();return`\n <div class="event-detail-card">\n <div class="event-detail-header">\n <div class="event-detail-title">\n ${this.getEventIcon(t)} ${t||"Unknown"}.${e.subtype||"default"}\n </div>\n <div class="event-detail-time">${s}</div>\n </div>\n <div class="event-detail-content">\n ${this.createProperty("Event ID",e.id||"N/A")}\n ${this.createProperty("Type",`${t}.${e.subtype||"default"}`)}\n ${this.createProperty("Class Events",n)}\n ${e.data&&e.data.session_id?this.createProperty("Session",e.data.session_id):""}\n </div>\n </div>\n `}createAgentStructuredView(t){const e=t.data||{};if("hook"===t.type&&"Task"===e.tool_name&&e.tool_parameters?.subagent_type){const n=e.tool_parameters;return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Agent Type",n.subagent_type)}\n ${this.createProperty("Task Type","Subagent Delegation")}\n ${this.createProperty("Phase",t.subtype||"pre_tool")}\n ${n.description?this.createProperty("Description",n.description):""}\n ${n.prompt?this.createProperty("Prompt Preview",this.truncateText(n.prompt,200)):""}\n ${e.session_id?this.createProperty("Session ID",e.session_id):""}\n ${e.working_directory?this.createProperty("Working Directory",e.working_directory):""}\n </div>\n ${n.prompt?`\n <div class="prompt-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">๐Ÿ“ Task Prompt</h3>\n </div>\n <div class="structured-data">\n <div class="task-prompt" style="white-space: pre-wrap; max-height: 300px; overflow-y: auto; padding: 10px; background: #f8fafc; border-radius: 6px; font-family: monospace; font-size: 12px; line-height: 1.4;">\n ${n.prompt}\n </div>\n </div>\n </div>\n `:""}\n </div>\n `}return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Agent Type",e.agent_type||e.subagent_type||"Unknown")}\n ${this.createProperty("Name",e.name||"N/A")}\n ${this.createProperty("Phase",t.subtype||"N/A")}\n ${e.config?this.createProperty("Config","object"==typeof e.config?Object.keys(e.config).join(", "):String(e.config)):""}\n ${e.capabilities?this.createProperty("Capabilities",e.capabilities.join(", ")):""}\n ${e.result?this.createProperty("Result","object"==typeof e.result?"[Object]":String(e.result)):""}\n </div>\n </div>\n `}createHookStructuredView(t){const e=t.data||{},n=this.extractFilePathFromHook(e),s=this.extractToolInfoFromHook(e),o=this.createInlineToolResultContent(e,t);return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Hook Name",this.getHookDisplayName(t,e))}\n ${this.createProperty("Event Type",e.event_type||t.subtype||"N/A")}\n ${n?this.createProperty("File Path",n):""}\n ${s.tool_name?this.createProperty("Tool",s.tool_name):""}\n ${s.operation_type?this.createProperty("Operation",s.operation_type):""}\n ${e.session_id?this.createProperty("Session ID",e.session_id):""}\n ${e.working_directory?this.createProperty("Working Directory",e.working_directory):""}\n ${e.duration_ms?this.createProperty("Duration",`${e.duration_ms}ms`):""}\n ${o}\n </div>\n </div>\n `}createInlineToolResultContent(t,e=null){const n=t.result_summary,s=e?.subtype||t.event_type||t.phase,o="post_tool"===s||s?.includes("post");if(window.DEBUG_TOOL_RESULTS&&console.log("๐Ÿ”ง createInlineToolResultContent debug:",{hasResultSummary:!!n,eventPhase:s,isPostTool:o,eventSubtype:e?.subtype,dataEventType:t.event_type,dataPhase:t.phase,toolName:t.tool_name,resultSummaryKeys:n?Object.keys(n):[]}),!n)return"";if("pre_tool"===s||s?.includes("pre")&&!s?.includes("post"))return"";let a="";if(n.has_output&&n.output_preview&&(a+=`\n ${this.createProperty("Output",this.truncateText(n.output_preview,200))}\n ${n.output_lines?this.createProperty("Output Lines",n.output_lines):""}\n `),n.has_error&&n.error_preview&&(a+=`\n ${this.createProperty("Error",this.truncateText(n.error_preview,200))}\n `),!n.has_output&&!n.has_error&&Object.keys(n).length>3){a+=Object.entries(n).filter(([t,e])=>!["has_output","has_error","exit_code"].includes(t)&&void 0!==e).map(([t,e])=>this.createProperty(this.formatFieldName(t),String(e))).join("")}return a}createToolResultSection(t,e=null){const n=t.result_summary,s=e?.subtype||t.event_type||t.phase,o="post_tool"===s||s?.includes("post");if(window.DEBUG_TOOL_RESULTS&&console.log("๐Ÿ”ง createToolResultSection debug:",{hasResultSummary:!!n,eventPhase:s,isPostTool:o,eventSubtype:e?.subtype,dataEventType:t.event_type,dataPhase:t.phase,toolName:t.tool_name,resultSummaryKeys:n?Object.keys(n):[]}),!n)return"";if("pre_tool"===s||s?.includes("pre")&&!s?.includes("post"))return"";let a="โณ",i="tool-running",r="Unknown";!0===t.success?(a="โœ…",i="tool-success",r="Success"):!1===t.success?(a="โŒ",i="tool-failure",r="Failed"):0===t.exit_code?(a="โœ…",i="tool-success",r="Completed"):2===t.exit_code?(a="โš ๏ธ",i="tool-blocked",r="Blocked"):void 0!==t.exit_code&&0!==t.exit_code&&(a="โŒ",i="tool-failure",r="Error");let l="";if(l+=`\n <div class="tool-result-status ${i}">\n <span class="tool-result-icon">${a}</span>\n <span class="tool-result-text">${r}</span>\n ${void 0!==t.exit_code?`<span class="tool-exit-code">Exit Code: ${t.exit_code}</span>`:""}\n </div>\n `,n.has_output&&n.output_preview&&(l+=`\n <div class="tool-result-output">\n <div class="tool-result-label">๐Ÿ“„ Output:</div>\n <div class="tool-result-preview">\n <pre>${this.escapeHtml(n.output_preview)}</pre>\n </div>\n ${n.output_lines?`<div class="tool-result-meta">Lines: ${n.output_lines}</div>`:""}\n </div>\n `),n.has_error&&n.error_preview&&(l+=`\n <div class="tool-result-error">\n <div class="tool-result-label">โš ๏ธ Error:</div>\n <div class="tool-result-preview error-preview">\n <pre>${this.escapeHtml(n.error_preview)}</pre>\n </div>\n </div>\n `),!n.has_output&&!n.has_error&&Object.keys(n).length>3){const t=Object.entries(n).filter(([t,e])=>!["has_output","has_error","exit_code"].includes(t)&&void 0!==e).map(([t,e])=>this.createProperty(this.formatFieldName(t),String(e))).join("");t&&(l+=`\n <div class="tool-result-other">\n <div class="tool-result-label">๐Ÿ“Š Result Details:</div>\n <div class="structured-data">\n ${t}\n </div>\n </div>\n `)}return l.trim()?`\n <div class="tool-result-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">๐Ÿ”ง Tool Result</h3>\n </div>\n <div class="tool-result-content">\n ${l}\n </div>\n </div>\n `:""}isWriteOperation(t,e){if(["Write","Edit","MultiEdit","NotebookEdit"].includes(t))return!0;if(e.tool_parameters){const t=e.tool_parameters;if(t.content||t.new_string||t.edits)return!0;if(t.edit_mode&&"read"!==t.edit_mode)return!0}return!("post_tool"!==e.event_type&&"pre_tool"!==e.event_type||!t||!(t.toLowerCase().includes("write")||t.toLowerCase().includes("edit")||t.toLowerCase().includes("modify")))}isReadOnlyOperation(t){if(!t)return!0;const e=t.toLowerCase();return!!["read"].includes(e)||!["write","edit","multiedit","create","delete","move","copy"].includes(e)}createTodoStructuredView(t){const e=t.data||{};let n="";return e.todos&&Array.isArray(e.todos)&&(n+=`\n <div class="todo-checklist">\n ${e.todos.map(t=>`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${this.getTodoStatusIcon(t.status)}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${this.getTodoPriorityIcon(t.priority)}</span>\n </div>\n `).join("")}\n </div>\n `),n}createMemoryStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Operation",e.operation||"Unknown")}\n ${this.createProperty("Key",e.key||"N/A")}\n ${e.value?this.createProperty("Value","object"==typeof e.value?"[Object]":String(e.value)):""}\n ${e.namespace?this.createProperty("Namespace",e.namespace):""}\n ${e.metadata?this.createProperty("Metadata","object"==typeof e.metadata?"[Object]":String(e.metadata)):""}\n </div>\n </div>\n `}createClaudeStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Type",t.subtype||"N/A")}\n ${e.prompt?this.createProperty("Prompt",this.truncateText(e.prompt,200)):""}\n ${e.message?this.createProperty("Message",this.truncateText(e.message,200)):""}\n ${e.response?this.createProperty("Response",this.truncateText(e.response,200)):""}\n ${e.content?this.createProperty("Content",this.truncateText(e.content,200)):""}\n ${e.tokens?this.createProperty("Tokens",e.tokens):""}\n ${e.model?this.createProperty("Model",e.model):""}\n </div>\n </div>\n `}createSessionStructuredView(t){const e=t.data||{};return`\n <div class="structured-view-section">\n <div class="structured-data">\n ${this.createProperty("Action",t.subtype||"N/A")}\n ${this.createProperty("Session ID",e.session_id||"N/A")}\n ${e.working_directory?this.createProperty("Working Dir",e.working_directory):""}\n ${e.git_branch?this.createProperty("Git Branch",e.git_branch):""}\n ${e.agent_type?this.createProperty("Agent Type",e.agent_type):""}\n </div>\n </div>\n `}createGenericStructuredView(t){const e=t.data||{},n=Object.keys(e);return 0===n.length?"":`\n <div class="structured-view-section">\n <div class="structured-data">\n ${n.map(t=>this.createProperty(t,"object"==typeof e[t]?"[Object]":String(e[t]))).join("")}\n </div>\n </div>\n `}createCollapsibleJsonSection(t){const e="json-section-"+Math.random().toString(36).substr(2,9),n=this.formatJSON(t),s=this.globalJsonExpanded;return`\n <div class="collapsible-json-section" id="${e}">\n <div class="json-toggle-header"\n onclick="window.moduleViewer.toggleJsonSection()"\n role="button"\n tabindex="0"\n aria-expanded="${s?"true":"false"}"\n onkeydown="if(event.key==='Enter'||event.key===' '){window.moduleViewer.toggleJsonSection();event.preventDefault();}">\n <span class="json-toggle-text">Raw JSON</span>\n <span class="json-toggle-arrow">${s?"โ–ฒ":"โ–ผ"}</span>\n </div>\n <div class="json-content-collapsible" style="display: ${s?"block":"none"};" aria-hidden="${!s}">\n <div class="json-display" onclick="window.moduleViewer.copyJsonToClipboard(event)">\n <pre>${n}</pre>\n </div>\n </div>\n </div>\n `}async copyJsonToClipboard(t){const e=t.currentTarget.getBoundingClientRect(),n=t.clientX-e.left,s=t.clientY-e.top;if(n>e.width-50&&s<30){const e=t.currentTarget.querySelector("pre");if(e)try{await navigator.clipboard.writeText(e.textContent),this.showNotification("JSON copied to clipboard","success")}catch(o){console.error("Failed to copy JSON:",o),this.showNotification("Failed to copy JSON","error")}t.stopPropagation()}}initializeJsonToggle(){window.moduleViewer=this,this.globalJsonExpanded&&setTimeout(()=>{this.updateAllJsonSections()},0),this.keyboardListenerAdded||(this.keyboardListenerAdded=!0,document.addEventListener("keydown",t=>{t.target.classList.contains("json-toggle-header")&&("Enter"!==t.key&&" "!==t.key||(this.toggleJsonSection(),t.preventDefault()))}))}toggleJsonSection(){this.globalJsonExpanded=!this.globalJsonExpanded,localStorage.setItem("dashboard-json-expanded",this.globalJsonExpanded.toString()),this.updateAllJsonSections(),document.dispatchEvent(new CustomEvent("jsonToggleChanged",{detail:{expanded:this.globalJsonExpanded}}))}updateAllJsonSections(){const t=document.querySelectorAll(".json-content-collapsible"),e=document.querySelectorAll(".json-toggle-arrow"),n=document.querySelectorAll(".json-toggle-header");t.forEach((t,s)=>{this.globalJsonExpanded?(t.style.display="block",t.setAttribute("aria-hidden","false"),e[s]&&(e[s].textContent="โ–ฒ"),n[s]&&n[s].setAttribute("aria-expanded","true")):(t.style.display="none",t.setAttribute("aria-hidden","true"),e[s]&&(e[s].textContent="โ–ผ"),n[s]&&n[s].setAttribute("aria-expanded","false"))}),this.globalJsonExpanded&&t.length>0&&setTimeout(()=>{const e=t[0];e&&e.scrollIntoView({behavior:"smooth",block:"nearest"})},100)}createProperty(t,e){const n=this.truncateText(String(e),300);return this.isFilePathProperty(t,e)?`\n <div class="event-property">\n <span class="event-property-key">${t}:</span>\n <span class="event-property-value">\n ${this.createClickableFilePath(e)}\n </span>\n </div>\n `:`\n <div class="event-property">\n <span class="event-property-key">${t}:</span>\n <span class="event-property-value">${n}</span>\n </div>\n `}isFilePathProperty(t,e){if(["File Path","file_path","notebook_path","Full Path","Working Directory","working_directory"].some(e=>t.toLowerCase().includes(e.toLowerCase()))){const t=String(e);return t.length>0&&(t.includes("/")||t.includes("\\"))&&t.length<500}return!1}createClickableFilePath(t){const e=this.truncateText(String(t),300);return`\n <span class="clickable-file-path"\n onclick="showFileViewerModal('${t.replace(/'/g,"\\'")}')"\n title="Click to view file contents with syntax highlighting&#10;Path: ${t}">\n ${e}\n </span>\n `}getEventIcon(t){const e={session:"๐Ÿ“ฑ",claude:"๐Ÿค–",agent:"๐ŸŽฏ",hook:"๐Ÿ”—",todo:"โœ…",memory:"๐Ÿง ",log:"๐Ÿ“",connection:"๐Ÿ”Œ",unknown:"โ“"};return e[t]||e.unknown}getTodoStatusIcon(t){const e={completed:"โœ…",in_progress:"๐Ÿ”„",pending:"โณ",cancelled:"โŒ"};return e[t]||e.pending}getTodoPriorityIcon(t){const e={high:"๐Ÿ”ด",medium:"๐ŸŸก",low:"๐ŸŸข"};return e[t]||e.medium}getHookDisplayName(t,e){if(e.hook_name)return e.hook_name;if(e.name)return e.name;const n=t.subtype||e.event_type,s={user_prompt:"User Prompt",pre_tool:"Tool Execution (Pre)",post_tool:"Tool Execution (Post)",notification:"Notification",stop:"Session Stop",subagent_stop:"Subagent Stop"};if(s[n])return s[n];if("string"==typeof t.type&&t.type.startsWith("hook.")){const e=t.type.replace("hook.","");if(s[e])return s[e]}return n?n.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" "):"Unknown Hook"}extractFilePathFromHook(t){return t.tool_parameters&&t.tool_parameters.file_path?t.tool_parameters.file_path:t.file_path?t.file_path:t.tool_input&&t.tool_input.file_path?t.tool_input.file_path:t.tool_parameters&&t.tool_parameters.notebook_path?t.tool_parameters.notebook_path:null}extractToolInfoFromHook(t){return{tool_name:t.tool_name||t.tool_parameters&&t.tool_parameters.tool_name,operation_type:t.operation_type||t.tool_parameters&&t.tool_parameters.operation_type}}truncateText(t,e){return!t||t.length<=e?t:t.substring(0,e)+"..."}formatOperationDetails(t){if(!t||"object"!=typeof t)return"";let e="";if(t.parameters&&t.parameters.command&&(e+=`<br><strong>Command:</strong> <code>${this.escapeHtml(t.parameters.command)}</code>`),void 0!==t.success&&(e+="<br><strong>Status:</strong> "+(t.success?"โœ… Success":"โŒ Failed")),void 0!==t.exit_code&&null!==t.exit_code&&(e+=`<br><strong>Exit Code:</strong> ${t.exit_code}`),void 0!==t.duration_ms&&null!==t.duration_ms){e+=`<br><strong>Duration:</strong> ${t.duration_ms>1e3?`${(t.duration_ms/1e3).toFixed(2)}s`:`${t.duration_ms}ms`}`}return t.error&&(e+=`<br><strong>Error:</strong> ${this.escapeHtml(this.truncateText(t.error,200))}`),e}escapeHtml(t){if(!t)return"";const e=document.createElement("div");return e.textContent=t,e.innerHTML}formatJSON(t){try{return JSON.stringify(t,null,2)}catch(e){return String(t)}}formatTimestamp(t){if(!t)return"Unknown time";try{return new Date(t).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit",hour12:!0})}catch(e){return"Invalid time"}}escapeHtml(t){if(!t)return"";const e=document.createElement("div");return e.textContent=t,e.innerHTML}formatFieldName(t){return t.split("_").map(t=>t.charAt(0).toUpperCase()+t.slice(1)).join(" ")}extractToolName(t){if(t.tool_name)return t.tool_name;if(t.tool_parameters&&t.tool_parameters.tool_name)return t.tool_parameters.tool_name;if(t.tool_input&&t.tool_input.tool_name)return t.tool_input.tool_name;if(t.tool_parameters){if(t.tool_parameters.file_path||t.tool_parameters.notebook_path)return"FileOperation";if(t.tool_parameters.pattern)return"Search";if(t.tool_parameters.command)return"Bash";if(t.tool_parameters.todos)return"TodoWrite"}return null}extractAgent(t){if(t._agentName&&"Unknown Agent"!==t._agentName)return t._agentName;if(t._inference&&t._inference.agentName&&"Unknown"!==t._inference.agentName)return t._inference.agentName;if(t.agent)return t.agent;if(t.agent_type)return t.agent_type;if(t.agent_name)return t.agent_name;if(t.session_id&&"string"==typeof t.session_id){const e=t.session_id.split("_");if(e.length>1)return e[0].toUpperCase()}return t.todos||"TodoWrite"===t.tool_name?"PM":null}extractFileName(t){const e=this.extractFilePathFromHook(t);if(e){const t=e.split("/");return t[t.length-1]}return t.filename?t.filename:t.file?t.file:null}clear(){this.unifiedViewer&&this.unifiedViewer.clear(),this.showEmptyState()}showToolCall(t,e){if(!t)return void this.showEmptyState();const n=t.tool_name||"Unknown Tool",s=t.agent_type||"PM",o=this.formatTimestamp(t.timestamp),a=t.pre_event,i=t.post_event,r=a?.tool_parameters||{},l=a?this.extractToolTarget(n,r):"Unknown target",c=t.duration_ms?`${t.duration_ms}ms`:"-",d=void 0!==t.success?t.success:null;void 0!==t.exit_code&&t.exit_code;let p=t.result_summary||"No summary available";if("object"==typeof p&&null!==p){const t=[];void 0!==p.exit_code&&t.push(`Exit Code: ${p.exit_code}`),void 0!==p.has_output&&t.push("Has Output: "+(p.has_output?"Yes":"No")),void 0!==p.has_error&&t.push("Has Error: "+(p.has_error?"Yes":"No")),void 0!==p.output_lines&&t.push(`Output Lines: ${p.output_lines}`),p.output_preview&&t.push(`Output Preview: ${p.output_preview}`),p.error_preview&&t.push(`Error Preview: ${p.error_preview}`)}let u="โณ",m="Running...",h="tool-running";i&&(!0===d?(u="โœ…",m="Success",h="tool-success"):!1===d?(u="โŒ",m="Failed",h="tool-failure"):(u="โณ",m="Completed",h="tool-completed"));const g=`\n <div class="contextual-header">\n <h3 class="contextual-header-text">${n}: ${s} ${o}</h3>\n </div>\n `;if("TodoWrite"===n&&r.todos){const e=`\n <div class="todo-checklist">\n ${r.todos.map(t=>{const e=this.getTodoStatusIcon(t.status),n=this.getTodoPriorityIcon(t.priority);return`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${e}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${n}</span>\n </div>\n `}).join("")}\n </div>\n `,n={toolCall:t,preEvent:a,postEvent:i},s=this.createCollapsibleJsonSection(n);this.dataContainer&&(this.dataContainer.innerHTML=g+e+s),this.initializeJsonToggle()}else if("Grep"===n||"Search"===n||r&&r.pattern&&!r.file_path){const e=r.pattern||"No pattern specified",o=r.path||r.directory||".",l=r.type||r.glob||"all files";let d="";t.result_summary&&(d="string"==typeof t.result_summary?t.result_summary:t.result_summary.output_preview?t.result_summary.output_preview:JSON.stringify(t.result_summary,null,2));const p=`\n <div class="structured-view-section">\n <div class="tool-call-details">\n <div class="tool-call-info ${h}">\n <div class="structured-field">\n <strong>Tool Name:</strong> ${n}\n </div>\n <div class="structured-field">\n <strong>Agent:</strong> ${s}\n </div>\n <div class="structured-field">\n <strong>Status:</strong> ${u} ${m}\n </div>\n <div class="structured-field">\n <strong>Search Pattern:</strong> <code>${e}</code>\n </div>\n <div class="structured-field">\n <strong>Search Path:</strong> ${o}\n </div>\n <div class="structured-field">\n <strong>File Type:</strong> ${l}\n </div>\n <div class="structured-field">\n <strong>Started:</strong> ${new Date(t.timestamp).toLocaleString()}\n </div>\n ${c&&"-"!==c?`\n <div class="structured-field">\n <strong>Duration:</strong> ${c}\n </div>\n `:""}\n </div>\n\n <div class="search-view-action" style="margin-top: 20px;">\n <button class="btn-view-search" data-search-params='${JSON.stringify(r)}' data-search-results='${JSON.stringify(d).replace(/'/g,"&#39;")}' onclick="window.showSearchViewerModal(JSON.parse(this.getAttribute('data-search-params')), JSON.parse(this.getAttribute('data-search-results')))">\n ๐Ÿ” View Search Details\n </button>\n </div>\n\n ${this.createToolResultFromToolCall(t)}\n </div>\n </div>\n `,v={toolCall:t,preEvent:a,postEvent:i},y=this.createCollapsibleJsonSection(v);this.dataContainer&&(this.dataContainer.innerHTML=g+p+y),this.initializeJsonToggle()}else{const e=`\n <div class="structured-view-section">\n <div class="tool-call-details">\n <div class="tool-call-info ${h}">\n <div class="structured-field">\n <strong>Tool Name:</strong> ${n}\n </div>\n <div class="structured-field">\n <strong>Agent:</strong> ${s}\n </div>\n <div class="structured-field">\n <strong>Status:</strong> ${u} ${m}\n </div>\n <div class="structured-field">\n <strong>Target:</strong> ${l}\n </div>\n <div class="structured-field">\n <strong>Started:</strong> ${new Date(t.timestamp).toLocaleString()}\n </div>\n ${c&&"-"!==c?`\n <div class="structured-field">\n <strong>Duration:</strong> ${c}\n </div>\n `:""}\n ${t.session_id?`\n <div class="structured-field">\n <strong>Session ID:</strong> ${t.session_id}\n </div>\n `:""}\n </div>\n\n ${this.createToolResultFromToolCall(t)}\n </div>\n </div>\n `,o={toolCall:t,preEvent:a,postEvent:i},r=this.createCollapsibleJsonSection(o);this.dataContainer&&(this.dataContainer.innerHTML=g+e+r),this.initializeJsonToggle()}}showFileOperations(e,n){if(!e||!n)return void this.showEmptyState();this.unifiedViewer||(this.unifiedViewer=new t("module-data-content"));const s={file_path:n,operations:e.operations||[],lastOperation:e.lastOperation,...e};this.unifiedViewer.display(s,"file_operation");const o=document.querySelector(".module-data-header h5");if(o){const t=n.split("/").pop()||n;o.textContent=`๐Ÿ“„ File: ${t}`}this.checkAndShowTrackControl(n)}showErrorMessage(t,e){const n=`\n <div class="module-error">\n <div class="error-header">\n <h3>โŒ ${t}</h3>\n </div>\n <div class="error-message">\n <p>${e}</p>\n </div>\n </div>\n `,s={title:t,message:e},o=this.createCollapsibleJsonSection(s);this.dataContainer&&(this.dataContainer.innerHTML=n+o),this.initializeJsonToggle()}showAgentEvent(t,e){this.showAgentSpecificDetails(t,e)}showAgentSpecificDetails(t,e){if(!t)return void this.showEmptyState();const n=window.dashboard?.agentInference,s=window.dashboard?.eventViewer;if(!n||!s)return console.warn("AgentInference or EventViewer not available, falling back to single event view"),void this.showEventDetails(t);const o=n.getInferredAgentForEvent(t),a=o?.agentName||this.extractAgent(t)||"Unknown",i=s.events||[],r=this.getAgentSpecificEvents(i,a,n);console.log(`Showing details for agent: ${a}, found ${r.length} related events`);const l=this.extractAgentSpecificData(a,r);this.renderAgentSpecificView(a,l,t)}getAgentSpecificEvents(t,e,n){return t.filter(t=>{const s=n.getInferredAgentForEvent(t);return(s?.agentName||this.extractAgent(t)||"Unknown").toLowerCase()===e.toLowerCase()})}extractAgentSpecificData(t,e){const n={agentName:t,totalEvents:e.length,prompt:null,todos:[],toolsCalled:[],sessions:new Set,firstSeen:null,lastSeen:null,eventTypes:new Set};return e.forEach(e=>{const s=e.data||{},o=new Date(e.timestamp);(!n.firstSeen||o<n.firstSeen)&&(n.firstSeen=o),(!n.lastSeen||o>n.lastSeen)&&(n.lastSeen=o),(e.session_id||s.session_id)&&n.sessions.add(e.session_id||s.session_id);const a=e.hook_event_name||e.type||"unknown";if(n.eventTypes.add(a),"hook"===e.type&&"Task"===s.tool_name&&s.tool_parameters){const e=s.tool_parameters;e.prompt&&!n.prompt&&(n.prompt=e.prompt),e.description&&!n.description&&(n.description=e.description),e.subagent_type===t&&e.prompt&&(n.prompt=e.prompt)}if(!s.prompt||s.agent_type!==t&&s.subagent_type!==t||(n.prompt=s.prompt),"todo"===e.type||"hook"===e.type&&"TodoWrite"===s.tool_name){const t=s.todos||s.tool_parameters?.todos;t&&Array.isArray(t)&&t.forEach(t=>{const e=n.todos.findIndex(e=>e.id===t.id||e.content===t.content);e>=0?n.todos[e]={...n.todos[e],...t,timestamp:o}:n.todos.push({...t,timestamp:o})})}if("hook"===e.type&&s.tool_name){const t=e.subtype||s.event_type,a=this.generateToolCallId(s.tool_name,s.tool_parameters,o);"pre_tool"===t?(n._preToolEvents||(n._preToolEvents=new Map),n._preToolEvents.set(a,{toolName:s.tool_name,timestamp:o,target:this.extractToolTarget(s.tool_name,s.tool_parameters,null),parameters:s.tool_parameters})):"post_tool"===t&&(n._postToolEvents||(n._postToolEvents=new Map),n._postToolEvents.set(a,{toolName:s.tool_name,timestamp:o,success:s.success,duration:s.duration_ms,resultSummary:s.result_summary,exitCode:s.exit_code}))}}),n.todos.sort((t,e)=>(e.timestamp||0)-(t.timestamp||0)),n.toolsCalled=this.consolidateToolCalls(n._preToolEvents,n._postToolEvents),delete n._preToolEvents,delete n._postToolEvents,n.toolsCalled.sort((t,e)=>e.timestamp-t.timestamp),n}generateToolCallId(t,e,n){const s=Math.floor(n.getTime()/5e3);let o="";if(e){const t=[];e.file_path&&t.push(e.file_path),e.command&&t.push(e.command.substring(0,50)),e.pattern&&t.push(e.pattern),e.subagent_type&&t.push(e.subagent_type),e.notebook_path&&t.push(e.notebook_path),e.url&&t.push(e.url),e.prompt&&t.push(e.prompt.substring(0,30)),o=t.join("|")}return o||(o="default"),`${t}:${s}:${o}`}consolidateToolCalls(t,e){const n=[],s=new Set;t||(t=new Map),e||(e=new Map);for(const[o,a]of t){if(s.has(o))continue;const t=e.get(o),i={toolName:a.toolName,timestamp:a.timestamp,target:a.target,parameters:a.parameters,status:this.determineToolCallStatus(a,t),statusIcon:this.getToolCallStatusIcon(a,t),phase:t?"completed":"running"};t&&(i.success=t.success,i.duration=t.duration,i.resultSummary=t.resultSummary,i.exitCode=t.exitCode,i.completedAt=t.timestamp),n.push(i),s.add(o)}for(const[o,a]of e){if(s.has(o))continue;const t={toolName:a.toolName,timestamp:a.timestamp,target:"Unknown target",parameters:null,status:this.determineToolCallStatus(null,a),statusIcon:this.getToolCallStatusIcon(null,a),phase:"completed",success:a.success,duration:a.duration,resultSummary:a.resultSummary,exitCode:a.exitCode,completedAt:a.timestamp};n.push(t),s.add(o)}return n}determineToolCallStatus(t,e){return e?!0===e.success?"Success":!1===e.success?"Failed":0===e.exitCode?"Completed":2===e.exitCode?"Blocked":void 0!==e.exitCode&&0!==e.exitCode?"Error":"Completed":"Running..."}getToolCallStatusIcon(t,e){return e?!0===e.success?"โœ…":!1===e.success?"โŒ":0===e.exitCode?"โœ…":2===e.exitCode?"โš ๏ธ":void 0!==e.exitCode&&0!==e.exitCode?"โŒ":"โœ…":"โณ"}estimateTokenCount(t){if(!t||"string"!=typeof t)return 0;const e=t.trim().split(/\s+/).length,n=Math.ceil(t.length/4);return Math.max(1.3*e,n)}trimPromptWhitespace(t){return t&&"string"==typeof t?t=(t=(t=t.trim()).replace(/\n\s*\n\s*\n+/g,"\n\n")).split("\n").map(t=>t.replace(/\s+$/,"")).join("\n"):""}renderAgentSpecificView(t,e,n){const s=this.formatTimestamp(n.timestamp),o=`\n <div class="contextual-header">\n <h3 class="contextual-header-text">๐Ÿค– ${t} Agent Details ${s}</h3>\n </div>\n `;let a=`\n <div class="agent-overview-section">\n <div class="structured-data">\n ${this.createProperty("Agent Name",t)}\n ${this.createProperty("Total Events",e.totalEvents)}\n ${this.createProperty("Active Sessions",e.sessions.size)}\n ${this.createProperty("Event Types",Array.from(e.eventTypes).join(", "))}\n ${e.firstSeen?this.createProperty("First Seen",e.firstSeen.toLocaleString()):""}\n ${e.lastSeen?this.createProperty("Last Seen",e.lastSeen.toLocaleString()):""}\n </div>\n </div>\n `;if(e.prompt){const t=this.trimPromptWhitespace(e.prompt);a+=`\n <div class="agent-prompt-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">๐Ÿ“ Agent Task Prompt</h3>\n <div class="prompt-stats" style="font-size: 11px; color: #64748b; margin-top: 4px;">\n ~${Math.round(this.estimateTokenCount(t))} tokens โ€ข ${t.trim().split(/\s+/).length} words โ€ข ${t.length} characters\n </div>\n </div>\n <div class="structured-data">\n <div class="agent-prompt" style="white-space: pre-wrap; max-height: 300px; overflow-y: auto; padding: 10px; background: #f8fafc; border-radius: 6px; font-family: monospace; font-size: 12px; line-height: 1.4; border: 1px solid #e2e8f0;">\n ${this.escapeHtml(t)}\n </div>\n </div>\n </div>\n `}e.todos.length>0&&(a+=`\n <div class="agent-todos-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">โœ… Agent Todo List (${e.todos.length} items)</h3>\n </div>\n <div class="todo-checklist">\n ${e.todos.map(t=>`\n <div class="todo-item todo-${t.status||"pending"}">\n <span class="todo-status">${this.getTodoStatusIcon(t.status)}</span>\n <span class="todo-content">${t.content||"No content"}</span>\n <span class="todo-priority priority-${t.priority||"medium"}">${this.getTodoPriorityIcon(t.priority)}</span>\n ${t.timestamp?`<span class="todo-timestamp">${new Date(t.timestamp).toLocaleTimeString()}</span>`:""}\n </div>\n `).join("")}\n </div>\n </div>\n `),e.toolsCalled.length>0&&(a+=`\n <div class="agent-tools-section">\n <div class="contextual-header">\n <h3 class="contextual-header-text">๐Ÿ”ง Tools Called by Agent (${e.toolsCalled.length} calls)</h3>\n </div>\n <div class="tools-list">\n ${e.toolsCalled.map(e=>{let n="";return"โœ…"===e.statusIcon?n="status-success":"โŒ"===e.statusIcon?n="status-failed":"โš ๏ธ"===e.statusIcon?n="status-blocked":"โณ"===e.statusIcon&&(n="status-running"),`\n <div class="tool-call-item">\n <div class="tool-call-header">\n <div style="display: flex; align-items: center; gap: 12px; flex: 1;">\n <span class="tool-name">๐Ÿ”ง ${e.toolName}</span>\n <span class="tool-agent">${t}</span>\n <span class="tool-status-indicator ${n}">${e.statusIcon} ${e.status}</span>\n </div>\n <span class="tool-timestamp" style="margin-left: auto;">${e.timestamp.toLocaleTimeString()}</span>\n </div>\n <div class="tool-call-details">\n ${e.target?`<span class="tool-target">Target: ${e.target}</span>`:""}\n ${e.duration?`<span class="tool-duration">Duration: ${e.duration}ms</span>`:""}\n ${e.completedAt&&e.completedAt!==e.timestamp?`<span class="tool-completed">Completed: ${e.completedAt.toLocaleTimeString()}</span>`:""}\n </div>\n </div>\n `}).join("")}\n </div>\n </div>\n `);const i={agentName:t,agentData:e,originalEvent:n},r=this.createCollapsibleJsonSection(i);this.dataContainer&&(this.dataContainer.innerHTML=o+a+r),this.initializeJsonToggle()}createToolResultFromToolCall(t){if(!t.result_summary)return"";const e={event_type:"post_tool",result_summary:t.result_summary,success:t.success,exit_code:t.exit_code},n=this.createInlineToolResultContent(e,{subtype:"post_tool"});return n.trim()?`\n <div class="tool-result-inline">\n <div class="structured-data">\n ${n}\n </div>\n </div>\n `:""}extractToolTarget(t,e,n){const s=e||n||{};switch(t?.toLowerCase()){case"write":case"read":case"edit":case"multiedit":return s.file_path||"Unknown file";case"bash":return s.command?`${s.command.substring(0,50)}${s.command.length>50?"...":""}`:"Unknown command";case"grep":return s.pattern?`Pattern: ${s.pattern}`:"Unknown pattern";case"glob":return s.pattern?`Pattern: ${s.pattern}`:"Unknown glob";case"todowrite":return`${s.todos?.length||0} todos`;case"task":return s.subagent_type||s.agent_type||"Subagent delegation";default:return s.file_path?s.file_path:s.pattern?`Pattern: ${s.pattern}`:s.command?`Command: ${s.command.substring(0,30)}...`:s.path?s.path:"Unknown target"}}getOperationIcon(t){return{read:"๐Ÿ‘๏ธ",write:"โœ๏ธ",edit:"๐Ÿ“",multiedit:"๐Ÿ“",create:"๐Ÿ†•",delete:"๐Ÿ—‘๏ธ",move:"๐Ÿ“ฆ",copy:"๐Ÿ“‹"}[t?.toLowerCase()]||"๐Ÿ“„"}getCurrentEvent(){return this.currentEvent}async checkAndShowTrackControl(t){if(t)try{const e=window.socket||window.dashboard?.socketClient?.socket;if(!e)return void console.warn("No socket connection available for git tracking check");let n=window.dashboard?.currentWorkingDir;if(!n||"Unknown"===n||""===n.trim()){const t=document.getElementById("footer-working-dir");n=t?.textContent?.trim()&&"Unknown"!==t.textContent.trim()?t.textContent.trim():".",console.log("[MODULE-VIEWER-DEBUG] Working directory fallback used:",n)}const s=new Promise((n,s)=>{const o=s=>{s.file_path===t&&(e.off("file_tracked_response",o),n(s))};e.on("file_tracked_response",o),setTimeout(()=>{e.off("file_tracked_response",o),s(new Error("Request timeout"))},5e3)});e.emit("check_file_tracked",{file_path:t,working_dir:n});const o=await s;this.displayTrackingStatus(t,o)}catch(e){console.error("Error checking file tracking status:",e),this.displayTrackingStatus(t,{success:!1,error:e.message,file_path:t})}}displayTrackingStatus(t,e){const n=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,s=document.getElementById(n);s&&(e.success&&!1===e.is_tracked?s.innerHTML=`\n <div class="untracked-file-notice">\n <span class="untracked-icon">โš ๏ธ</span>\n <span class="untracked-text">This file is not tracked by git</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Add this file to git tracking">\n <span class="git-icon">๐Ÿ“</span> Track File\n </button>\n </div>\n `:e.success&&!0===e.is_tracked?s.innerHTML='\n <div class="tracked-file-notice">\n <span class="tracked-icon">โœ…</span>\n <span class="tracked-text">This file is tracked by git</span>\n </div>\n ':e.success||(s.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">โŒ</span>\n <span class="error-text">Could not check git status: ${e.error||"Unknown error"}</span>\n </div>\n `))}async trackFile(t){if(t)try{const e=window.socket||window.dashboard?.socketClient?.socket;if(!e)return void console.warn("No socket connection available for git add");let n=window.dashboard?.currentWorkingDir;if(!n||"Unknown"===n||""===n.trim()){const t=document.getElementById("footer-working-dir");n=t?.textContent?.trim()&&"Unknown"!==t.textContent.trim()?t.textContent.trim():".",console.log("[MODULE-VIEWER-DEBUG] Working directory fallback used:",n)}const s=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,o=document.getElementById(s);o&&(o.innerHTML='\n <div class="tracking-file-notice">\n <span class="loading-icon">โณ</span>\n <span class="loading-text">Adding file to git tracking...</span>\n </div>\n ');const a=new Promise((n,s)=>{const o=s=>{s.file_path===t&&(e.off("git_add_response",o),n(s))};e.on("git_add_response",o),setTimeout(()=>{e.off("git_add_response",o),s(new Error("Request timeout"))},1e4)});e.emit("git_add_file",{file_path:t,working_dir:n}),console.log("๐Ÿ“ Git add request sent:",{filePath:t,workingDir:n});const i=await a;console.log("๐Ÿ“ฆ Git add result:",i),i.success?(o&&(o.innerHTML='\n <div class="tracked-file-notice">\n <span class="tracked-icon">โœ…</span>\n <span class="tracked-text">File successfully added to git tracking</span>\n </div>\n '),this.showNotification("File tracked successfully","success")):(o&&(o.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">โŒ</span>\n <span class="error-text">Failed to track file: ${i.error||"Unknown error"}</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Try again">\n <span class="git-icon">๐Ÿ“</span> Retry\n </button>\n </div>\n `),this.showNotification(`Failed to track file: ${i.error}`,"error"))}catch(e){console.error("โŒ Failed to track file:",e);const n=`git-track-status-${t.replace(/[^a-zA-Z0-9]/g,"-")}`,s=document.getElementById(n);s&&(s.innerHTML=`\n <div class="tracking-error-notice">\n <span class="error-icon">โŒ</span>\n <span class="error-text">Error: ${e.message}</span>\n <button class="track-file-button"\n onclick="window.moduleViewer.trackFile('${t}')"\n title="Try again">\n <span class="git-icon">๐Ÿ“</span> Retry\n </button>\n </div>\n `),this.showNotification(`Error tracking file: ${e.message}`,"error")}}showNotification(t,e="info"){const n=document.createElement("div");n.className=`notification notification-${e}`,n.innerHTML=`\n <span class="notification-icon">${"success"===e?"โœ…":"error"===e?"โŒ":"โ„น๏ธ"}</span>\n <span class="notification-message">${t}</span>\n `,n.style.cssText=`\n position: fixed;\n top: 20px;\n right: 20px;\n background: ${"success"===e?"#d4edda":"error"===e?"#f8d7da":"#d1ecf1"};\n color: ${"success"===e?"#155724":"error"===e?"#721c24":"#0c5460"};\n border: 1px solid ${"success"===e?"#c3e6cb":"error"===e?"#f5c6cb":"#bee5eb"};\n border-radius: 6px;\n padding: 12px 16px;\n font-size: 14px;\n font-weight: 500;\n z-index: 2000;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n display: flex;\n align-items: center;\n gap: 8px;\n max-width: 400px;\n animation: slideIn 0.3s ease-out;\n `;const s=document.createElement("style");s.textContent="\n @keyframes slideIn {\n from { transform: translateX(100%); opacity: 0; }\n to { transform: translateX(0); opacity: 1; }\n }\n @keyframes slideOut {\n from { transform: translateX(0); opacity: 1; }\n to { transform: translateX(100%); opacity: 0; }\n }\n ",document.head.appendChild(s),document.body.appendChild(n),setTimeout(()=>{n.style.animation="slideOut 0.3s ease-in",setTimeout(()=>{n.parentNode&&n.parentNode.removeChild(n),s.parentNode&&s.parentNode.removeChild(s)},300)},5e3)}showAgentInstance(t){if(!t)return void this.showEmptyState();const e={type:"pm_delegation",subtype:t.agentName,agent_type:t.agentName,timestamp:t.timestamp,session_id:t.sessionId,metadata:{delegation_type:"explicit",event_count:t.agentEvents.length,pm_call:t.pmCall||null,agent_events:t.agentEvents}};console.log("Showing PM delegation details:",t),this.showAgentSpecificDetails(e,0)}showImpliedAgent(t){if(!t)return void this.showEmptyState();const e={type:"implied_delegation",subtype:t.agentName,agent_type:t.agentName,timestamp:t.timestamp,session_id:t.sessionId,metadata:{delegation_type:"implied",event_count:t.eventCount,pm_call:null,note:"No explicit PM call found - inferred from agent activity"}};console.log("Showing implied agent details:",t),this.showAgentSpecificDetails(e,0)}},window.enableToolResultDebugging=function(){window.DEBUG_TOOL_RESULTS=!0,console.log("๐Ÿ”ง Tool result debugging enabled. Click on tool events to see debug info.")},window.disableToolResultDebugging=function(){window.DEBUG_TOOL_RESULTS=!1,console.log("๐Ÿ”ง Tool result debugging disabled.")};
2
- //# sourceMappingURL=module-viewer.js.map
@@ -1,2 +0,0 @@
1
- window.refreshSessions=function(){window.sessionManager&&window.sessionManager.refreshSessions()},window.SessionManager=class{constructor(e){this.socketClient=e,this.sessions=new Map,this.currentSessionId=null,this.selectedSessionId="",this.init()}init(){this.setupEventHandlers(),this.setupSocketListeners(),this.updateSessionSelect()}setupEventHandlers(){const e=document.getElementById("session-select");e&&e.addEventListener("change",e=>{this.selectedSessionId=e.target.value,this.onSessionFilterChanged(),window.dashboard&&window.dashboard.loadWorkingDirectoryForSession&&window.dashboard.loadWorkingDirectoryForSession(e.target.value)});const s=document.querySelector('button[onclick="refreshSessions()"]');s&&s.addEventListener("click",()=>{this.refreshSessions()})}setupSocketListeners(){this.socketClient.onEventUpdate((e,s)=>{console.log("[SESSION-MANAGER] Received sessions update:",s),this.sessions=s,this.updateSessionSelect(),this.updateFooterInfo()}),document.addEventListener("socketConnectionStatus",e=>{"connected"===e.detail.type&&setTimeout(()=>this.refreshSessions(),1e3)})}updateSessionSelect(){const e=document.getElementById("session-select");if(!e)return;const s=e.value;let t="/";if(window.dashboard&&window.dashboard.workingDirectoryManager)t=window.dashboard.workingDirectoryManager.getDefaultWorkingDir();else{const e=document.getElementById("working-dir-path");if(e?.textContent?.trim()){const s=e.textContent.trim();"Loading..."!==s&&"Unknown"!==s&&(t=s)}}if(console.log("[SESSION-MANAGER] Using default working directory:",t),e.innerHTML=`\n <option value="">${t} | All Sessions</option>\n `,this.sessions&&this.sessions.size>0){Array.from(this.sessions.values()).sort((e,s)=>new Date(s.lastActivity||s.startTime)-new Date(e.lastActivity||e.startTime)).forEach(s=>{const n=document.createElement("option");n.value=s.id,new Date(s.startTime||s.last_activity).toLocaleString(),s.eventCount||s.event_count;const o=s.id===this.currentSessionId;let i=s.working_directory||s.workingDirectory||"";if(console.log(`[SESSION-DROPDOWN] Session ${s.id.substring(0,8)} working_directory:`,i),!i){i=this.extractSessionInfoFromEvents(s.id).workingDir||t,console.log("[SESSION-DROPDOWN] Extracted working directory from events:",i)}const r=s.id.substring(0,8),a=i||t;n.textContent=`${a} | ${r}...${o?" [ACTIVE]":""}`,e.appendChild(n)})}s&&Array.from(e.options).some(e=>e.value===s)?(e.value=s,this.selectedSessionId=s,this.onSessionFilterChanged()):(this.selectedSessionId=e.value,this.selectedSessionId&&this.onSessionFilterChanged())}onSessionFilterChanged(){const e=window.eventViewer;e&&e.setSessionFilter(this.selectedSessionId),this.updateFooterInfo(),document.dispatchEvent(new CustomEvent("sessionFilterChanged",{detail:{sessionId:this.selectedSessionId}})),document.dispatchEvent(new CustomEvent("sessionChanged",{detail:{sessionId:this.selectedSessionId}}))}refreshSessions(){this.socketClient&&this.socketClient.getConnectionState().isConnected?(console.log("Refreshing sessions..."),this.socketClient.requestStatus()):console.warn("Cannot refresh sessions: not connected to server")}updateFooterInfo(){console.log("[SESSION-DEBUG] updateFooterInfo called, selectedSessionId:",this.selectedSessionId);const e=document.getElementById("footer-session"),s=document.getElementById("footer-working-dir"),t=document.getElementById("footer-git-branch");if(!e)return void console.warn("[SESSION-DEBUG] footer-session element not found");let n="All Sessions",o=window.dashboard?.workingDirectoryManager?.getDefaultWorkingDir()||window.dashboardConfig?.workingDirectory||".",i="Unknown";if(console.log("[SESSION-DEBUG] Initial values - sessionInfo:",n,"workingDir:",o,"gitBranch:",i),"current"===this.selectedSessionId){if(n=this.currentSessionId?`Current: ${this.currentSessionId.substring(0,8)}...`:"Current: None",this.currentSessionId){const e=this.extractSessionInfoFromEvents(this.currentSessionId);o=e.workingDir||window.dashboard?.workingDirectoryManager?.getDefaultWorkingDir()||window.dashboardConfig?.workingDirectory||".",i=e.gitBranch||"Unknown"}}else if(this.selectedSessionId){const e=this.sessions.get(this.selectedSessionId);if(e&&(n=`${this.selectedSessionId.substring(0,8)}...`,o=e.working_directory||e.workingDirectory||"",i=e.git_branch||e.gitBranch||"",!o||!i)){const e=this.extractSessionInfoFromEvents(this.selectedSessionId);o=o||e.workingDir||window.dashboardConfig?.workingDirectory||".",i=i||e.gitBranch||""}}console.log("[SESSION-DEBUG] Final values before setting footer - sessionInfo:",n,"workingDir:",o,"gitBranch:",i),e.textContent=n,s?(console.log("[SESSION-DEBUG] Setting footer working dir to:",o),s.textContent=o):console.warn("[SESSION-DEBUG] footer-working-dir element not found"),t?(console.log("[SESSION-DEBUG] Setting footer git branch to:",i),t.textContent=i):console.warn("[SESSION-DEBUG] footer-git-branch element not found")}extractSessionInfoFromEvents(e){let s="",t="";console.log(`[DEBUG] extractSessionInfoFromEvents called for sessionId: ${e}`);const n=this.socketClient;if(n&&n.events){console.log(`[DEBUG] Total events available: ${n.events.length}`);const o=n.events.filter(s=>s.data&&s.data.session_id===e);console.log(`[DEBUG] Events matching sessionId ${e}: ${o.length}`),o.length>0&&(console.log(`[DEBUG] Sample events for session ${e}:`),o.slice(0,3).forEach((e,s)=>{console.log(`[DEBUG] Event ${s+1}:`,{type:e.type,timestamp:e.timestamp,data_keys:e.data?Object.keys(e.data):"no data",full_event:e})}),o.length>3&&(console.log(`[DEBUG] Last 3 events for session ${e}:`),o.slice(-3).forEach((e,s)=>{console.log(`[DEBUG] Last Event ${s+1}:`,{type:e.type,timestamp:e.timestamp,data_keys:e.data?Object.keys(e.data):"no data",full_event:e})})));for(let e=o.length-1;e>=0;e--){const n=o[e];if(n.data){if(console.log(`[DEBUG] Examining event ${e} data:`,n.data),s||(n.data.working_directory?(s=n.data.working_directory,console.log(`[DEBUG] Found working_directory: ${s}`)):n.data.cwd?(s=n.data.cwd,console.log(`[DEBUG] Found cwd: ${s}`)):n.data.instance_info&&n.data.instance_info.working_dir&&(s=n.data.instance_info.working_dir,console.log(`[DEBUG] Found instance_info.working_dir: ${s}`))),!t){const e=["git_branch","gitBranch","branch","git.branch","vcs_branch","current_branch"];for(const s of e)if(n.data[s]){t=n.data[s],console.log(`[DEBUG] Found git branch in field '${s}': ${t}`);break}if(!t){if(n.data.instance_info){console.log("[DEBUG] Checking instance_info for branch:",n.data.instance_info);for(const s of e)if(n.data.instance_info[s]){t=n.data.instance_info[s],console.log(`[DEBUG] Found git branch in instance_info.${s}: ${t}`);break}}!t&&n.data.git&&(console.log("[DEBUG] Checking git object:",n.data.git),n.data.git.branch&&(t=n.data.git.branch,console.log(`[DEBUG] Found git branch in git.branch: ${t}`)))}}if(s&&t){console.log("[DEBUG] Found both workingDir and gitBranch, stopping search");break}}}}else console.log("[DEBUG] No socket client or events available");return console.log(`[DEBUG] Final results - workingDir: '${s}', gitBranch: '${t}'`),{workingDir:s,gitBranch:t}}setCurrentSessionId(e){this.currentSessionId=e,this.updateSessionSelect(),this.updateFooterInfo()}addSession(e){if(!e.id)return;const s=this.sessions.get(e.id);s?Object.assign(s,e):this.sessions.set(e.id,{id:e.id,startTime:e.startTime||e.start_time||(new Date).toISOString(),lastActivity:e.lastActivity||e.last_activity||(new Date).toISOString(),eventCount:e.eventCount||e.event_count||0,working_directory:e.working_directory||e.workingDirectory||"",git_branch:e.git_branch||e.gitBranch||"",agent_type:e.agent_type||e.agentType||"",...e}),this.updateSessionSelect()}removeSession(e){if(this.sessions.has(e)){if(this.sessions.delete(e),this.selectedSessionId===e){this.selectedSessionId="";const e=document.getElementById("session-select");e&&(e.value=""),this.onSessionFilterChanged()}this.updateSessionSelect()}}getCurrentFilter(){return this.selectedSessionId}getSession(e){return this.sessions.get(e)||null}getAllSessions(){return this.sessions}getCurrentSessionId(){return this.currentSessionId}clearSessions(){this.sessions.clear(),this.currentSessionId=null,this.selectedSessionId="",this.updateSessionSelect(),this.updateFooterInfo()}exportSessionData(){return{sessions:Array.from(this.sessions.entries()),currentSessionId:this.currentSessionId,selectedSessionId:this.selectedSessionId}}importSessionData(e){e.sessions&&Array.isArray(e.sessions)&&(this.sessions.clear(),e.sessions.forEach(([e,s])=>{this.sessions.set(e,s)})),e.currentSessionId&&(this.currentSessionId=e.currentSessionId),void 0!==e.selectedSessionId&&(this.selectedSessionId=e.selectedSessionId),this.updateSessionSelect(),this.updateFooterInfo()}getEventsForSession(e){if(!e||!this.socketClient)return[];return(this.socketClient.events||[]).filter(s=>(s.session_id||s.data&&s.data.session_id||null)===e)}};
2
- //# sourceMappingURL=session-manager.js.map
@@ -1,2 +0,0 @@
1
- import{S as a,S as e}from"../socket-client.js";export{a as SocketManager,e as default};
2
- //# sourceMappingURL=socket-manager.js.map
@@ -1,2 +0,0 @@
1
- import{U as a,U as t}from"../socket-client.js";export{a as UIStateManager,t as default};
2
- //# sourceMappingURL=ui-state-manager.js.map
@@ -1,2 +0,0 @@
1
- class e{constructor(e="module-data-content"){this.container=document.getElementById(e),this.currentData=null,this.currentType=null,this.globalJsonExpanded="true"===localStorage.getItem("dashboard-json-expanded"),this.fullEventDataExpanded="true"===localStorage.getItem("dashboard-full-event-expanded"),document.addEventListener("jsonToggleChanged",e=>{this.globalJsonExpanded=e.detail.expanded,this.updateAllJsonSections()}),document.addEventListener("fullEventToggleChanged",e=>{this.fullEventDataExpanded=e.detail.expanded,this.updateAllFullEventSections()})}display(e,n=null){if(this.container)switch(this.currentData=e,this.currentType=n,n||(n=this.detectType(e)),this.container.innerHTML="",n){case"event":this.displayEvent(e);break;case"agent":this.displayAgent(e);break;case"tool":this.displayTool(e);break;case"todo":this.displayTodo(e);break;case"instruction":this.displayInstruction(e);break;case"session":this.displaySession(e);break;case"file_operation":if(e.name&&(e.params||e.tool_parameters)){const n=this.convertToolToFileOperation(e);this.displayFileOperation(n)}else this.displayFileOperation(e);break;case"hook":this.displayHook(e);break;default:this.displayGeneric(e)}else console.warn("UnifiedDataViewer: Container not found")}detectType(e){return e&&"object"==typeof e?e.hook_event_name||e.event_type||e.type&&e.timestamp?"event":e.agent_name||e.agentName||e.name&&("active"===e.status||"completed"===e.status)?"agent":e.tool_name||"TodoWrite"===e.name||"Read"===e.name||e.tool_parameters||e.params&&e.icon||e.name&&"tool"===e.type?"tool":!e.todos||e.name||e.params?e.content&&e.activeForm&&e.status&&!e.name&&!e.params?"todo":e.text&&e.preview&&"user_instruction"===e.type?"instruction":e.session_id&&(e.startTime||e.lastActivity)?"session":e.file_path&&(e.operations||e.operation)?"file_operation":"Read"!==e.name&&"Write"!==e.name&&"Edit"!==e.name&&"MultiEdit"!==e.name&&"Grep"!==e.name&&"Glob"!==e.name||!e.params?.file_path&&!e.tool_parameters?.file_path?e.event_type&&(e.hook_name||e.subtype)?"hook":"generic":"file_operation":"todo":"generic"}displayEvent(e){let n=`\n <div class="unified-viewer-header">\n <h6>${this.formatEventType(e)}</h6>\n <span class="unified-viewer-timestamp">${this.formatTimestamp(e.timestamp)}</span>\n </div>\n <div class="unified-viewer-content">\n `;if(n+='<div class="primary-data">',n+=this.formatEventDetails(e),e.tool_name||e.data?.tool_name){const t=e.tool_name||e.data.tool_name;n+=`\n <div class="detail-row highlight">\n <span class="detail-label">Tool:</span>\n <span class="detail-value">${this.getToolIcon(t)} ${t}</span>\n </div>\n `;const a=e.tool_parameters||e.data?.tool_parameters;a&&(a.file_path&&(n+=`\n <div class="detail-row">\n <span class="detail-label">File:</span>\n <span class="detail-value code">${a.file_path}</span>\n </div>\n `),a.command&&(n+=`\n <div class="detail-row">\n <span class="detail-label">Command:</span>\n <pre class="code-snippet">${this.escapeHtml(a.command)}</pre>\n </div>\n `))}n+="</div>",n+=this.createCollapsibleJSON(e,"Full Event Data"),n+="</div>",this.container.innerHTML=n}displayAgent(e){const n=this.getAgentIcon(e.name||e.agentName),t=e.name||e.agentName||"Unknown Agent",a=this.formatStatus(e.status);let s=`\n <div class="unified-viewer-header">\n <h6>${n} ${t}</h6>\n <span class="unified-viewer-status">${a}</span>\n </div>\n <div class="unified-viewer-content">\n `;if(s+='<div class="primary-data">',s+=`\n <div class="detail-row highlight">\n <span class="detail-label">Status:</span>\n <span class="detail-value ${this.formatStatusClass(a)}">${a}</span>\n </div>\n `,e.tools&&e.tools.length>0){const n=e.tools.filter(e=>"in_progress"===e.status),t=e.tools.filter(e=>"completed"===e.status);n.length>0&&(s+='\n <div class="active-tools-section">\n <span class="section-label">๐Ÿ”„ Active Tools:</span>\n <div class="tools-grid">\n ',n.forEach(e=>{s+=`\n <div class="tool-chip active">\n ${this.getToolIcon(e.name)} ${e.name}\n </div>\n `}),s+="</div></div>"),s+=`\n <div class="detail-row">\n <span class="detail-label">Tools Summary:</span>\n <span class="detail-value">\n ${n.length} active, ${t.length} completed, ${e.tools.length} total\n </span>\n </div>\n `}(e.currentTask||e.description)&&(s+=`\n <div class="detail-row">\n <span class="detail-label">Current Task:</span>\n <span class="detail-value">${e.currentTask||e.description}</span>\n </div>\n `),s+="</div>",s+=this.createCollapsibleJSON(e,"Full Agent Details"),s+="</div>",this.container.innerHTML=s}displayTool(e){const n=e.name||e.tool_name||"Unknown Tool",t=this.getToolIcon(n),a=this.formatStatus(e.status);if("TodoWrite"===n)return void this.displayTodoWriteTool(e);let s=`\n <div class="unified-viewer-header">\n <h6>${t} ${n}</h6>\n <span class="unified-viewer-status">${a}</span>\n </div>\n <div class="unified-viewer-content">\n `;const i=e.params||e.tool_parameters||{};"Read"===n||"Edit"===n||"Write"===n?i.file_path&&(s+=`\n <div class="primary-data">\n <div class="detail-row highlight">\n <span class="detail-label">๐Ÿ“ File:</span>\n <span class="detail-value code">${i.file_path}</span>\n </div>\n `,i.old_string&&(s+=`\n <div class="detail-row">\n <span class="detail-label">Old Text:</span>\n <pre class="code-snippet">${this.escapeHtml(i.old_string.substring(0,200))}${i.old_string.length>200?"...":""}</pre>\n </div>\n `),i.new_string&&(s+=`\n <div class="detail-row">\n <span class="detail-label">New Text:</span>\n <pre class="code-snippet">${this.escapeHtml(i.new_string.substring(0,200))}${i.new_string.length>200?"...":""}</pre>\n </div>\n `),s+="</div>"):"Bash"===n?i.command&&(s+=`\n <div class="primary-data">\n <div class="detail-row highlight">\n <span class="detail-label">๐Ÿ’ป Command:</span>\n <pre class="code-snippet">${this.escapeHtml(i.command)}</pre>\n </div>\n </div>\n `):"Grep"===n||"Glob"===n?i.pattern&&(s+=`\n <div class="primary-data">\n <div class="detail-row highlight">\n <span class="detail-label">๐Ÿ” Pattern:</span>\n <span class="detail-value code">${this.escapeHtml(i.pattern)}</span>\n </div>\n `,i.path&&(s+=`\n <div class="detail-row">\n <span class="detail-label">Path:</span>\n <span class="detail-value">${i.path}</span>\n </div>\n `),s+="</div>"):"Task"===n&&i.subagent_type&&(s+=`\n <div class="primary-data">\n <div class="detail-row highlight">\n <span class="detail-label">๐Ÿค– Delegating to:</span>\n <span class="detail-value">${i.subagent_type} agent</span>\n </div>\n `,i.description&&(s+=`\n <div class="detail-row">\n <span class="detail-label">Task:</span>\n <span class="detail-value">${i.description}</span>\n </div>\n `),s+="</div>"),s+=`\n <div class="detail-row">\n <span class="detail-label">Status:</span>\n <span class="detail-value">${a}</span>\n </div>\n `,e.callCount&&(s+=`\n <div class="detail-row">\n <span class="detail-label">Call Count:</span>\n <span class="detail-value">${e.callCount}</span>\n </div>\n `),s+=this.createCollapsibleJSON(e,"Full Tool Details"),s+="</div>",this.container.innerHTML=s}displayTodoWriteTool(e){const n=this.formatStatus(e.status),t=(e.params||e.tool_parameters||{}).todos||[];let a=`\n <div class="unified-viewer-header">\n <h6>๐Ÿ“ TodoWrite</h6>\n <span class="unified-viewer-status">${n}</span>\n </div>\n <div class="unified-viewer-content">\n `;if(t.length>0){const e=this.getTodoStatusCounts(t);a+=`\n <div class="todo-status-line">\n <span class="status-inline">โœ… ${e.completed} Done</span>\n <span class="status-inline">๐Ÿ”„ ${e.in_progress} Active</span>\n <span class="status-inline">โณ ${e.pending} Pending</span>\n </div>\n `,a+='\n <div class="todo-list-primary">\n ',t.forEach((e,n)=>{const t=this.getCheckboxIcon(e.status),s="in_progress"===e.status&&e.activeForm||e.content,i=this.formatStatusClass(e.status);a+=`\n <div class="todo-item ${e.status}">\n <span class="todo-icon ${i}">${t}</span>\n <span class="todo-text">${this.escapeHtml(s)}</span>\n ${"in_progress"===e.status?'<span class="todo-badge active">ACTIVE</span>':""}\n </div>\n `}),a+="\n </div>\n "}else a+='\n <div class="detail-row">\n <span class="detail-value">No todos in list</span>\n </div>\n ';e.callCount&&e.callCount>1&&(a+=`\n <div class="detail-row">\n <span class="detail-label">Updates:</span>\n <span class="detail-value">${e.callCount}</span>\n </div>\n `),a+=this.createCollapsibleJSON(e,"Full Details"),a+="</div>",this.container.innerHTML=a}displayTodo(e){let n;n=e.todos&&Array.isArray(e.todos)?e.todos:Array.isArray(e)?e:e.content&&e.activeForm&&e.status?[e]:[];let t='\n <div class="unified-viewer-header">\n <h6>๐Ÿ“‹ Todo List</h6>\n </div>\n <div class="unified-viewer-content">\n ';n.length>0?(t+='\n <div class="todo-list-primary">\n ',n.forEach(e=>{const n=this.getCheckboxIcon(e.status),a="in_progress"===e.status&&e.activeForm||e.content,s=this.formatStatusClass(e.status);t+=`\n <div class="todo-item ${e.status}">\n <span class="todo-icon ${s}">${n}</span>\n <span class="todo-text">${this.escapeHtml(a)}</span>\n <span class="todo-status-text ${s}">${e.status.replace("_"," ")}</span>\n </div>\n `}),t+="\n </div>\n "):t+='\n <div class="detail-section">\n <div class="no-todos">No todo items found</div>\n </div>\n ',t+="</div>",this.container.innerHTML=t}displayInstruction(e){let n=`\n <div class="unified-viewer-header">\n <h6>๐Ÿ’ฌ User Instruction</h6>\n <span class="unified-viewer-timestamp">${this.formatTimestamp(e.timestamp)}</span>\n </div>\n <div class="unified-viewer-content">\n `;n+=`\n <div class="primary-data">\n <div class="instruction-content">\n ${this.escapeHtml(e.text)}\n </div>\n <div class="instruction-meta">\n <span class="meta-item">๐Ÿ“ ${e.text.length} characters</span>\n <span class="meta-item">๐Ÿ• ${this.formatTimestamp(e.timestamp)}</span>\n </div>\n </div>\n `,Object.keys(e).length>3&&(n+=this.createCollapsibleJSON(e,"Full Instruction Data")),n+="</div>",this.container.innerHTML=n}displaySession(e){let n=`\n <div class="unified-viewer-header">\n <h6>๐ŸŽฏ Session: ${e.session_id||e.id}</h6>\n <span class="unified-viewer-status">${this.formatStatus(e.status||"active")}</span>\n </div>\n <div class="unified-viewer-content">\n <div class="detail-row">\n <span class="detail-label">Session ID:</span>\n <span class="detail-value">${e.session_id||e.id}</span>\n </div>\n <div class="detail-row">\n <span class="detail-label">Start Time:</span>\n <span class="detail-value">${this.formatTimestamp(e.startTime||e.timestamp)}</span>\n </div>\n `;e.working_directory&&(n+=`\n <div class="detail-row">\n <span class="detail-label">Working Directory:</span>\n <span class="detail-value">${e.working_directory}</span>\n </div>\n `),e.git_branch&&(n+=`\n <div class="detail-row">\n <span class="detail-label">Git Branch:</span>\n <span class="detail-value">${e.git_branch}</span>\n </div>\n `),void 0!==e.eventCount&&(n+=`\n <div class="detail-row">\n <span class="detail-label">Events:</span>\n <span class="detail-value">${e.eventCount}</span>\n </div>\n `),n+="</div>",this.container.innerHTML=n}displayFileOperation(e){const n=e.file_path?e.file_path.split("/").pop():"Unknown File",t=this.isSingleFileOperation(e),a=this.getFileIcon(e.file_path),s=this.getFileType(e.file_path);let i=`\n <div class="unified-viewer-header ${t?"single-file-header":""}">\n <h6>${a} File: ${n}</h6>\n <span class="unified-viewer-count">${e.operations?e.operations.length:1} operation${e.operations&&1!==e.operations.length?"s":""}</span>\n ${s?`<span class="file-type-badge">${s}</span>`:""}\n </div>\n <div class="unified-viewer-content">\n <div class="primary-data">\n <div class="detail-row highlight">\n <span class="detail-label">๐Ÿ“ File Path:</span>\n <span class="detail-value code clickable-file-path" \n onclick="window.showFileViewerModal && window.showFileViewerModal('${e.file_path}')"\n title="Click to view file contents\\nKeyboard: Hover + V key or Ctrl/Cmd + Click\\nFile: ${e.file_path}"\n tabindex="0"\n role="button"\n aria-label="Open file ${e.file_path} in viewer"\n onkeypress="if(event.key==='Enter'||event.key===' '){window.showFileViewerModal && window.showFileViewerModal('${e.file_path}')}">${e.file_path}</span>\n </div>\n `;if(e.file_path){const n=this.shouldShowInlinePreview(e);if(i+=`\n <div class="file-actions ${t?"single-file-actions":""}">\n <button class="file-action-btn view-file-btn ${t?"primary-action":""}" \n onclick="window.showFileViewerModal && window.showFileViewerModal('${e.file_path}')"\n title="View file contents with syntax highlighting">\n ${a} View File Contents\n </button>\n ${t&&this.isTextFile(e.file_path)?`\n <button class="file-action-btn inline-preview-btn" \n onclick="window.unifiedDataViewer && window.unifiedDataViewer.toggleInlinePreview('${e.file_path}', this)"\n title="Toggle inline preview">\n ๐Ÿ“– Quick Preview\n </button>\n `:""}\n </div>\n `,t&&n){i+=`\n <div class="inline-preview-container" id="preview-${this.generatePreviewId(e.file_path)}" style="display: none;">\n <div class="inline-preview-loading">Loading preview...</div>\n </div>\n `}}i+="</div>",e.operations&&Array.isArray(e.operations)&&(i+=`\n <div class="detail-section">\n <span class="detail-section-title">Operations (${e.operations.length}):</span>\n <div class="operations-list">\n ${e.operations.map((e,n)=>`\n <div class="operation-item">\n <div class="operation-header">\n <span class="operation-type">${this.getOperationIcon(e.operation)} ${e.operation}</span>\n <span class="operation-timestamp">${this.formatTimestamp(e.timestamp)}</span>\n </div>\n <div class="operation-details">\n <span class="operation-agent">by ${e.agent||"Unknown"}</span>\n ${e.workingDirectory?`<span class="operation-dir">in ${e.workingDirectory}</span>`:""}\n </div>\n </div>\n `).join("")}\n </div>\n </div>\n `),i+=this.createCollapsibleJSON(e,"Full File Data"),i+="</div>",this.container.innerHTML=i}displayHook(e){let n=`\n <div class="unified-viewer-header">\n <h6>๐Ÿ”— Hook: ${e.event_type||e.subtype||"unknown"}</h6>\n <span class="unified-viewer-timestamp">${this.formatTimestamp(e.timestamp)}</span>\n </div>\n <div class="unified-viewer-content">\n `;n+=this.formatHookDetails(e),n+="</div>",this.container.innerHTML=n}displayGeneric(e){let n=`\n <div class="unified-viewer-header">\n <h6>๐Ÿ“Š Data Details</h6>\n ${e.timestamp?`<span class="unified-viewer-timestamp">${this.formatTimestamp(e.timestamp)}</span>`:""}\n </div>\n <div class="unified-viewer-content">\n `;if("object"==typeof e&&null!==e){const t=["id","name","type","status","timestamp","text","content","message"];for(let a of t)if(void 0!==e[a]){let t=e[a];"string"==typeof t&&t.length>200&&(t=t.substring(0,200)+"..."),n+=`\n <div class="detail-row">\n <span class="detail-label">${a}:</span>\n <span class="detail-value">${this.escapeHtml(String(t))}</span>\n </div>\n `}}else n+=`<div class="simple-value">${this.escapeHtml(String(e))}</div>`;n+="</div>",this.container.innerHTML=n}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.hook_event_name?e.hook_event_name:"unknown"}formatEventDetails(e){switch(e.data,e.type){case"hook":return this.formatHookDetails(e);case"agent":return this.formatAgentEventDetails(e);case"todo":return this.formatTodoEventDetails(e);case"session":return this.formatSessionEventDetails(e);default:return this.formatGenericEventDetails(e)}}formatHookDetails(e){const n=e.data||{},t=e.subtype||e.event_type||"unknown";let a=`\n <div class="detail-row">\n <span class="detail-label">Hook Type:</span>\n <span class="detail-value">${t}</span>\n </div>\n `;switch(t){case"user_prompt":const e=n.prompt_text||n.prompt_preview||"";a+=`\n <div class="detail-row">\n <span class="detail-label">Prompt:</span>\n <div class="detail-value prompt-text">${this.escapeHtml(e)}</div>\n </div>\n `;break;case"pre_tool":case"post_tool":a+=`\n <div class="detail-row">\n <span class="detail-label">Tool:</span>\n <span class="detail-value">${n.tool_name||"Unknown tool"}</span>\n </div>\n `,n.operation_type&&(a+=`\n <div class="detail-row">\n <span class="detail-label">Operation:</span>\n <span class="detail-value">${n.operation_type}</span>\n </div>\n `),"post_tool"===t&&n.duration_ms&&(a+=`\n <div class="detail-row">\n <span class="detail-label">Duration:</span>\n <span class="detail-value">${n.duration_ms}ms</span>\n </div>\n `);break;case"subagent_start":case"subagent_stop":a+=`\n <div class="detail-row">\n <span class="detail-label">Agent:</span>\n <span class="detail-value">${n.agent_type||n.agent||"Unknown"}</span>\n </div>\n `,"subagent_start"===t&&n.prompt&&(a+=`\n <div class="detail-row">\n <span class="detail-label">Task:</span>\n <div class="detail-value">${this.escapeHtml(n.prompt)}</div>\n </div>\n `),"subagent_stop"===t&&n.reason&&(a+=`\n <div class="detail-row">\n <span class="detail-label">Reason:</span>\n <span class="detail-value">${n.reason}</span>\n </div>\n `)}return a}formatAgentEventDetails(e){const n=e.data||{};let t="";return(n.agent_type||n.name)&&(t+=`\n <div class="detail-row">\n <span class="detail-label">Agent Type:</span>\n <span class="detail-value">${n.agent_type||n.name}</span>\n </div>\n `),e.subtype&&(t+=`\n <div class="detail-row">\n <span class="detail-label">Action:</span>\n <span class="detail-value">${e.subtype}</span>\n </div>\n `),t}formatTodoEventDetails(e){const n=e.data||{};let t="";if(n.todos&&Array.isArray(n.todos)){const e=this.getTodoStatusCounts(n.todos);t+=`\n <div class="detail-row">\n <span class="detail-label">Todo Items:</span>\n <span class="detail-value">${n.todos.length} total</span>\n </div>\n <div class="detail-row">\n <span class="detail-label">Status:</span>\n <span class="detail-value">${e.completed} completed, ${e.in_progress} in progress</span>\n </div>\n `}return t}formatSessionEventDetails(e){const n=e.data||{};let t="";return n.session_id&&(t+=`\n <div class="detail-row">\n <span class="detail-label">Session ID:</span>\n <span class="detail-value">${n.session_id}</span>\n </div>\n `),e.subtype&&(t+=`\n <div class="detail-row">\n <span class="detail-label">Action:</span>\n <span class="detail-value">${e.subtype}</span>\n </div>\n `),t}formatGenericEventDetails(e){const n=e.data||{};let t="";const a=["message","description","value","result"];for(let s of a)if(void 0!==n[s]){let e=n[s];"string"==typeof e&&e.length>200&&(e=e.substring(0,200)+"..."),t+=`\n <div class="detail-row">\n <span class="detail-label">${s}:</span>\n <span class="detail-value">${this.escapeHtml(String(e))}</span>\n </div>\n `}return t}formatEventData(e){const n=e.data;return n&&0!==Object.keys(n).length?`\n <div class="detail-section">\n <span class="detail-section-title">Event Data:</span>\n <pre class="event-data-json">${this.escapeHtml(JSON.stringify(n,null,2))}</pre>\n </div>\n `:""}formatParameters(e,n="Parameters"){if(!e||0===Object.keys(e).length)return`\n <div class="detail-section">\n <span class="detail-section-title">${n}:</span>\n <div class="no-params">No parameters</div>\n </div>\n `;const t=Object.keys(e);return`\n <div class="detail-section">\n <span class="detail-section-title">${n} (${t.length}):</span>\n <div class="params-list">\n ${t.map(n=>{const t=e[n];return`\n <div class="param-item">\n <div class="param-key">${n}:</div>\n <div class="param-value">${this.formatParameterValue(t)}</div>\n </div>\n `}).join("")}\n </div>\n </div>\n `}formatParameterValue(e){if("string"==typeof e)return e.length>500?`<pre class="param-text-long">${this.escapeHtml(e.substring(0,500)+"...\n\n[Content truncated - "+e.length+" total characters]")}</pre>`:e.length>100?`<pre class="param-text">${this.escapeHtml(e)}</pre>`:`<span class="param-text-short">${this.escapeHtml(e)}</span>`;if("object"!=typeof e||null===e)return`<span class="param-primitive">${this.escapeHtml(String(e))}</span>`;if(Array.isArray(e)&&e.length>0&&e[0].hasOwnProperty("content")&&e[0].hasOwnProperty("status"))return this.formatTodosAsParameter(e);try{return`<pre class="param-json">${this.escapeHtml(JSON.stringify(e,null,2))}</pre>`}catch(n){return'<span class="param-error">Error displaying object</span>'}}formatTodosAsParameter(e){const n=this.getTodoStatusCounts(e);let t=`\n <div class="param-todos">\n <div class="param-todos-header">\n Array of todo objects (${e.length} items)\n </div>\n <div class="param-todos-summary">\n ${n.completed} completed โ€ข ${n.in_progress} in progress โ€ข ${n.pending} pending\n </div>\n <div class="param-todos-list">\n `;return e.forEach((e,n)=>{const a=this.getCheckboxIcon(e.status),s="in_progress"===e.status&&e.activeForm||e.content,i=this.formatStatusClass(e.status);t+=`\n <div class="param-todo-item ${e.status}">\n <div class="param-todo-checkbox">\n <span class="param-checkbox-icon ${i}">${a}</span>\n </div>\n <div class="param-todo-text">\n <span class="param-todo-content">${this.escapeHtml(s)}</span>\n <span class="param-todo-status-badge ${i}">${e.status.replace("_"," ")}</span>\n </div>\n </div>\n `}),t+="\n </div>\n </div>\n ",t}isSingleFileOperation(e){return!e.operations||1===e.operations.length}getFileIcon(e){if(!e)return"๐Ÿ“„";const n=e.split(".").pop()?.toLowerCase();return{js:"๐ŸŸจ",jsx:"โš›๏ธ",ts:"๐Ÿ”ท",tsx:"โš›๏ธ",py:"๐Ÿ",java:"โ˜•",cpp:"โšก",c:"โšก",cs:"#๏ธโƒฃ",php:"๐Ÿ˜",rb:"๐Ÿ’Ž",go:"๐Ÿน",rs:"๐Ÿฆ€",swift:"๐Ÿฆ‰",kt:"๐Ÿ…บ",scala:"๐ŸŽฏ",html:"๐ŸŒ",htm:"๐ŸŒ",css:"๐ŸŽจ",scss:"๐ŸŽจ",sass:"๐ŸŽจ",less:"๐ŸŽจ",vue:"๐Ÿ’š",json:"๐Ÿ“‹",xml:"๐Ÿ“„",yaml:"โš™๏ธ",yml:"โš™๏ธ",toml:"โš™๏ธ",ini:"โš™๏ธ",conf:"โš™๏ธ",config:"โš™๏ธ",md:"๐Ÿ“",txt:"๐Ÿ“ƒ",rtf:"๐Ÿ“ƒ",pdf:"๐Ÿ“•",doc:"๐Ÿ“˜",docx:"๐Ÿ“˜",jpg:"๐Ÿ–ผ๏ธ",jpeg:"๐Ÿ–ผ๏ธ",png:"๐Ÿ–ผ๏ธ",gif:"๐Ÿ–ผ๏ธ",svg:"๐ŸŽจ",webp:"๐Ÿ–ผ๏ธ",ico:"๐Ÿ–ผ๏ธ",zip:"๐Ÿ—œ๏ธ",tar:"๐Ÿ—œ๏ธ",gz:"๐Ÿ—œ๏ธ",rar:"๐Ÿ—œ๏ธ","7z":"๐Ÿ—œ๏ธ",sql:"๐Ÿ—ƒ๏ธ",db:"๐Ÿ—ƒ๏ธ",log:"๐Ÿ“Š",env:"๐Ÿ”",lock:"๐Ÿ”’"}[n]||"๐Ÿ“„"}getFileType(e){if(!e)return null;const n=e.split(".").pop()?.toLowerCase();return{js:"JavaScript",jsx:"React JSX",ts:"TypeScript",tsx:"React TSX",py:"Python",java:"Java",cpp:"C++",c:"C",cs:"C#",php:"PHP",rb:"Ruby",go:"Go",rs:"Rust",html:"HTML",css:"CSS",scss:"SCSS",json:"JSON",xml:"XML",yaml:"YAML",yml:"YAML",md:"Markdown",txt:"Text",sql:"SQL",log:"Log File"}[n]||null}shouldShowInlinePreview(e){return this.isSingleFileOperation(e)&&this.isTextFile(e.file_path)}isTextFile(e){if(!e)return!1;const n=e.split(".").pop()?.toLowerCase();return["txt","md","json","xml","yaml","yml","ini","conf","config","js","jsx","ts","tsx","py","java","cpp","c","cs","php","rb","go","rs","swift","kt","scala","html","htm","css","scss","sass","less","vue","sql","log","env","gitignore","dockerignore"].includes(n)}async toggleInlinePreview(e,n){const t=`preview-${this.generatePreviewId(e)}`,a=document.getElementById(t);a?"none"===a.style.display?(a.style.display="block",n.innerHTML="๐Ÿ“– Hide Preview",await this.loadInlinePreview(e,a)):(a.style.display="none",n.innerHTML="๐Ÿ“– Quick Preview"):console.warn("Preview container not found")}async loadInlinePreview(e,n){try{n.innerHTML=`\n <div class="inline-preview-header">\n <span class="preview-label">Quick Preview:</span>\n <span class="preview-file">${e}</span>\n </div>\n <div class="inline-preview-content">\n <div class="preview-note">\n ๐Ÿ’ก Inline preview feature ready - API integration needed\n <br>Click "View File Contents" for full syntax-highlighted view\n </div>\n </div>\n `}catch(t){n.innerHTML=`\n <div class="inline-preview-error">\n โŒ Could not load preview: ${t.message}\n </div>\n `}}generateId(){return Date.now().toString(36)+Math.random().toString(36).substr(2,9)}generatePreviewId(e){return btoa(e).replace(/[^a-zA-Z0-9]/g,"")}formatTimestamp(e){if(!e)return"Unknown time";try{const n=new Date(e);return isNaN(n.getTime())?"Invalid date":n.toLocaleString()}catch(n){return"Invalid date"}}formatStatus(e){if(!e)return"unknown";return{active:"๐ŸŸข Active",completed:"โœ… Completed",in_progress:"๐Ÿ”„ In Progress",pending:"โณ Pending",error:"โŒ Error",failed:"โŒ Failed"}[e]||e}formatStatusClass(e){return`status-${e}`}getAgentIcon(e){return{PM:"๐ŸŽฏ",Engineer:"๐Ÿ”ง","Engineer Agent":"๐Ÿ”ง",Research:"๐Ÿ”","Research Agent":"๐Ÿ”",QA:"โœ…","QA Agent":"โœ…",Architect:"๐Ÿ—๏ธ","Architect Agent":"๐Ÿ—๏ธ",Ops:"โš™๏ธ","Ops Agent":"โš™๏ธ"}[e]||"๐Ÿค–"}getToolIcon(e){return{Read:"๐Ÿ‘๏ธ",Write:"โœ๏ธ",Edit:"โœ๏ธ",MultiEdit:"๐Ÿ“",Bash:"๐Ÿ’ป",Grep:"๐Ÿ”",Glob:"๐Ÿ“‚",LS:"๐Ÿ“",TodoWrite:"๐Ÿ“",Task:"๐Ÿ“‹",WebFetch:"๐ŸŒ"}[e]||"๐Ÿ”ง"}getCheckboxIcon(e){return{pending:"โณ",in_progress:"๐Ÿ”„",completed:"โœ…"}[e]||"โ“"}getOperationIcon(e){return{read:"๐Ÿ‘๏ธ",write:"โœ๏ธ",edit:"โœ๏ธ",delete:"๐Ÿ—‘๏ธ",create:"๐Ÿ“",search:"๐Ÿ”",list:"๐Ÿ“‚",copy:"๐Ÿ“‹",move:"๐Ÿ“ฆ",bash:"๐Ÿ’ป"}[e.toLowerCase()]||"๐Ÿ“„"}convertToolToFileOperation(e){const n=e.params||e.tool_parameters||{},t=n.file_path||n.path||n.notebook_path;if(!t)return e;const a={operation:e.name.toLowerCase(),timestamp:e.timestamp||(new Date).toISOString(),agent:"Activity Tool",sessionId:e.sessionId||"unknown",details:{parameters:n,tool_name:e.name,status:e.status||"completed"}};return{file_path:t,operations:[a],lastOperation:a.timestamp,originalTool:e}}getTodoStatusCounts(e){const n={completed:0,in_progress:0,pending:0};return e.forEach(e=>{n.hasOwnProperty(e.status)&&n[e.status]++}),n}escapeHtml(e){if("string"!=typeof e)return"";const n=document.createElement("div");return n.textContent=e,n.innerHTML}toggleJsonSection(e,n){this.globalJsonExpanded=!this.globalJsonExpanded,localStorage.setItem("dashboard-json-expanded",this.globalJsonExpanded.toString()),this.updateAllJsonSections(),document.dispatchEvent(new CustomEvent("jsonToggleChanged",{detail:{expanded:this.globalJsonExpanded}}))}toggleFullEventSection(e,n){this.fullEventDataExpanded=!this.fullEventDataExpanded,localStorage.setItem("dashboard-full-event-expanded",this.fullEventDataExpanded.toString()),this.updateAllFullEventSections(),document.dispatchEvent(new CustomEvent("fullEventToggleChanged",{detail:{expanded:this.fullEventDataExpanded}}))}updateAllJsonSections(){const e=document.querySelectorAll(".unified-json-content"),n=document.querySelectorAll(".unified-json-toggle");e.forEach(e=>{this.globalJsonExpanded?e.style.display="block":e.style.display="none"}),n.forEach(e=>{const n=e.textContent.substring(2);this.globalJsonExpanded?(e.innerHTML="โ–ผ "+n,e.classList.add("expanded")):(e.innerHTML="โ–ถ "+n,e.classList.remove("expanded"))})}updateAllFullEventSections(){const e=document.querySelectorAll(".full-event-content"),n=document.querySelectorAll(".full-event-toggle");e.forEach(e=>{this.fullEventDataExpanded?e.style.display="block":e.style.display="none"}),n.forEach(e=>{const n=e.textContent.substring(2);this.fullEventDataExpanded?(e.innerHTML="โ–ผ "+n,e.classList.add("expanded")):(e.innerHTML="โ–ถ "+n,e.classList.remove("expanded"))})}createCollapsibleJSON(e,n="Full Details"){const t=`json-details-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,a=this.cleanDataForDisplay(e),s=n.includes("Full Event")||n.includes("Full Details")||n.includes("Full Agent")||n.includes("Full Tool"),i=s?this.fullEventDataExpanded:this.globalJsonExpanded;return`\n <div class="collapsible-json-section">\n <button class="collapsible-json-toggle ${s?"full-event-toggle":"unified-json-toggle"} ${i?"expanded":""}" \n data-section-id="${t}"\n data-is-full-event="${s}"\n onclick="window.unifiedDataViewer.${s?"toggleFullEventSection":"toggleJsonSection"}('${t}', this)">\n ${i?"โ–ผ":"โ–ถ"} ${n}\n </button>\n <div id="${t}" class="collapsible-json-content ${s?"full-event-content":"unified-json-content"}" style="display: ${i?"block":"none"};">\n <pre class="json-viewer">${this.escapeHtml(JSON.stringify(a,null,2))}</pre>\n </div>\n </div>\n `}cleanDataForDisplay(e){const n=new WeakSet;return JSON.parse(JSON.stringify(e,(e,t)=>{if("object"==typeof t&&null!==t){if(n.has(t))return"[Circular Reference]";n.add(t)}return"string"==typeof t&&t.length>1e3?t.substring(0,1e3)+"... [truncated]":"function"==typeof t?"[Function]":t}))}clear(){this.container&&(this.container.innerHTML=""),this.currentData=null,this.currentType=null}getCurrentData(){return this.currentData}getCurrentType(){return this.currentType}hasData(){return null!==this.currentData}}window.UnifiedDataViewer=e,"undefined"!=typeof window&&(window.unifiedDataViewer=new e,window.toggleFullEventSection=function(e,n){window.unifiedDataViewer&&window.unifiedDataViewer.toggleFullEventSection(e,n)},window.toggleJsonSection=function(e,n){window.unifiedDataViewer&&window.unifiedDataViewer.toggleJsonSection(e,n)}),"undefined"!=typeof window&&window.addEventListener("DOMContentLoaded",function(){window.unifiedDataViewer||(window.unifiedDataViewer=new e),document.addEventListener("keydown",function(e){if((e.ctrlKey||e.metaKey)&&e.target.classList.contains("clickable-file-path")){e.preventDefault();const n=e.target.textContent.trim();window.showFileViewerModal&&window.showFileViewerModal(n)}if("v"===e.key.toLowerCase()&&document.querySelector(".clickable-file-path:hover")){const n=document.querySelector(".clickable-file-path:hover");if(n&&window.showFileViewerModal){e.preventDefault();const t=n.textContent.trim();window.showFileViewerModal(t)}}})});export{e as U};
2
- //# sourceMappingURL=unified-data-viewer.js.map
@@ -1,2 +0,0 @@
1
- window.WorkingDirectoryManager=class{constructor(e){this.socketManager=e,this.currentWorkingDir=null,this.footerDirObserver=null,this._updatingFooter=!1,this.setupEventHandlers(),this.initialize(),console.log("Working directory manager initialized")}initialize(){this.initializeWorkingDirectory(),this.watchFooterDirectory()}setupEventHandlers(){const e=document.getElementById("change-dir-btn"),t=document.getElementById("working-dir-path");if(e&&e.addEventListener("click",()=>{this.showChangeDirDialog()}),t&&t.addEventListener("click",e=>{e.shiftKey?this.showChangeDirDialog():this.showWorkingDirectoryViewer()}),document.addEventListener("sessionChanged",e=>{const t=e.detail.sessionId;console.log("[WORKING-DIR-DEBUG] sessionChanged event received, sessionId:",this.repr(t)),t&&this.loadWorkingDirectoryForSession(t)}),this.socketManager&&this.socketManager.getSocket){const e=this.socketManager.getSocket();e&&(console.log("[WORKING-DIR-DEBUG] Setting up git_branch_response listener"),e.on("git_branch_response",e=>{console.log("[GIT-BRANCH-DEBUG] Received git_branch_response:",e),this.handleGitBranchResponse(e)}))}}initializeWorkingDirectory(){const e=document.getElementById("working-dir-path");e&&!e.textContent.trim()&&(e.textContent="Loading...");const t=document.getElementById("session-select");t&&t.value&&"all"!==t.value?this.loadWorkingDirectoryForSession(t.value):this.setWorkingDirectory(this.getDefaultWorkingDir())}watchFooterDirectory(){const e=document.getElementById("footer-working-dir");e&&(this.footerDirObserver=new MutationObserver(t=>{this._updatingFooter||t.forEach(t=>{if("childList"===t.type||"characterData"===t.type){const t=e.textContent.trim();console.log("Footer directory changed to:",t),t&&t!==this.currentWorkingDir&&(console.log("Syncing working directory from footer change"),this.setWorkingDirectory(t))}})}),this.footerDirObserver.observe(e,{childList:!0,characterData:!0,subtree:!0}),console.log("Started watching footer directory for changes"))}loadWorkingDirectoryForSession(e){if(console.log("[WORKING-DIR-DEBUG] loadWorkingDirectoryForSession called with sessionId:",this.repr(e)),!e||"all"===e){console.log('[WORKING-DIR-DEBUG] No sessionId or sessionId is "all", using default working dir');const e=this.getDefaultWorkingDir();return console.log("[WORKING-DIR-DEBUG] Default working dir:",this.repr(e)),void this.setWorkingDirectory(e)}const t=JSON.parse(localStorage.getItem("sessionWorkingDirs")||"{}");console.log("[WORKING-DIR-DEBUG] Session directories from localStorage:",t);const r=t[e],o=this.getDefaultWorkingDir(),i=r||o;console.log("[WORKING-DIR-DEBUG] Directory selection:",{sessionId:e,sessionDir:this.repr(r),defaultDir:this.repr(o),finalDir:this.repr(i)}),this.setWorkingDirectory(i)}setWorkingDirectory(e){console.log("[WORKING-DIR-DEBUG] setWorkingDirectory called with:",this.repr(e)),this.currentWorkingDir=e,e&&this.validateDirectoryPath(e)&&(sessionStorage.setItem("currentWorkingDirectory",e),console.log("[WORKING-DIR-DEBUG] Stored working directory in session storage:",e));const t=document.getElementById("working-dir-path");t?(console.log("[WORKING-DIR-DEBUG] Updating UI path element to:",e),t.textContent=e):console.warn("[WORKING-DIR-DEBUG] working-dir-path element not found");const r=document.getElementById("footer-working-dir");if(r){const t=r.textContent;console.log("[WORKING-DIR-DEBUG] Footer directory current text:",this.repr(t),"new text:",this.repr(e)),t!==e?(this._updatingFooter=!0,r.textContent=e,console.log("[WORKING-DIR-DEBUG] Updated footer directory to:",e),setTimeout(()=>{this._updatingFooter=!1,console.log("[WORKING-DIR-DEBUG] Cleared _updatingFooter flag")},100)):console.log("[WORKING-DIR-DEBUG] Footer directory already has correct text")}else console.warn("[WORKING-DIR-DEBUG] footer-working-dir element not found");const o=document.getElementById("session-select");if(o&&o.value&&"all"!==o.value){const t=o.value,r=JSON.parse(localStorage.getItem("sessionWorkingDirs")||"{}");r[t]=e,localStorage.setItem("sessionWorkingDirs",JSON.stringify(r)),console.log(`[WORKING-DIR-DEBUG] Saved working directory for session ${t}:`,e)}else console.log('[WORKING-DIR-DEBUG] No session selected or session is "all", not saving to localStorage');console.log("[WORKING-DIR-DEBUG] About to call updateGitBranch with:",this.repr(e)),this.validateDirectoryPath(e)?this.updateGitBranch(e):console.log("[WORKING-DIR-DEBUG] Skipping git branch update for invalid directory:",this.repr(e)),document.dispatchEvent(new CustomEvent("workingDirectoryChanged",{detail:{directory:e}})),console.log("[WORKING-DIR-DEBUG] Working directory set to:",e)}updateGitBranch(e){if(console.log("[GIT-BRANCH-DEBUG] updateGitBranch called with dir:",this.repr(e),"type:",typeof e),!this.socketManager||!this.socketManager.isConnected()){console.log("[GIT-BRANCH-DEBUG] Not connected to socket server");const e=document.getElementById("footer-git-branch");return void(e&&(e.textContent="Not Connected",e.style.display="inline"))}const t=this.validateDirectoryPath(e),r="Loading..."===e||"Loading"===e,o="Unknown"===e,i=!e||"string"==typeof e&&""===e.trim();if(console.log("[GIT-BRANCH-DEBUG] Validation results:",{dir:e,isValidPath:t,isLoadingState:r,isUnknown:o,isEmptyOrWhitespace:i,shouldReject:!t||r||o||i}),!t||r||o||i){console.warn("[GIT-BRANCH-DEBUG] Invalid working directory for git branch request:",e);const t=document.getElementById("footer-git-branch");return void(t&&(t.textContent=r?"Loading...":o||i?"No Directory":"Invalid Directory",t.style.display="inline"))}const n=this.socketManager.getSocket();n?(console.log("[GIT-BRANCH-DEBUG] Requesting git branch for directory:",e),console.log("[GIT-BRANCH-DEBUG] Socket state:",{connected:n.connected,id:n.id}),n.emit("get_git_branch",e)):console.error("[GIT-BRANCH-DEBUG] No socket available for git branch request")}getDefaultWorkingDir(){if(console.log("[WORKING-DIR-DEBUG] getDefaultWorkingDir called"),this.currentWorkingDir&&this.validateDirectoryPath(this.currentWorkingDir))return console.log("[WORKING-DIR-DEBUG] Using current working directory:",this.currentWorkingDir),this.currentWorkingDir;const e=document.querySelector(".working-dir-text");if(e?.textContent?.trim()){const t=e.textContent.trim();if("Loading..."!==t&&"Unknown"!==t&&this.validateDirectoryPath(t))return console.log("[WORKING-DIR-DEBUG] Using header working directory:",t),t}const t=document.getElementById("footer-working-dir");if(t?.textContent?.trim()){const e=t.textContent.trim();console.log("[WORKING-DIR-DEBUG] Footer path found:",this.repr(e));const r="Unknown"===e,o=this.validateDirectoryPath(e);if(console.log("[WORKING-DIR-DEBUG] Footer path validation:",{footerPath:this.repr(e),isUnknown:r,isValid:o,shouldUse:!r&&o}),!r&&o)return console.log("[WORKING-DIR-DEBUG] Using footer path as default:",e),e}else console.log("[WORKING-DIR-DEBUG] No footer directory element or no text content");if(window.socketClient&&window.socketClient.events){const e=window.socketClient.events.filter(e=>e.data&&(e.data.working_directory||e.data.cwd||e.data.working_dir)).reverse();if(e.length>0){const t=e[0],r=t.data.working_directory||t.data.cwd||t.data.working_dir;return console.log("[WORKING-DIR-DEBUG] Using working directory from recent event:",r),r}}const r=document.getElementById("working-dir-path");if(r?.textContent?.trim()){const e=r.textContent.trim();if(console.log("[WORKING-DIR-DEBUG] Found working-dir-path element text:",this.repr(e)),"Unknown"!==e&&this.validateDirectoryPath(e))return console.log("[WORKING-DIR-DEBUG] Using working-dir-path as fallback:",e),e}const o=sessionStorage.getItem("currentWorkingDirectory");if(o&&this.validateDirectoryPath(o))return console.log("[WORKING-DIR-DEBUG] Using session storage working directory:",this.repr(o)),o;const i=window.processWorkingDirectory||process?.cwd?.()||null;if(i&&this.validateDirectoryPath(i))return console.log("[WORKING-DIR-DEBUG] Using process working directory:",this.repr(i)),i;const n=window.homeDirectory||process?.env?.HOME||process?.env?.USERPROFILE||null||process?.cwd?.()||os?.homedir?.()||"/Users/masa";return console.log("[WORKING-DIR-DEBUG] Using fallback directory (home or cwd):",this.repr(n)),n}showChangeDirDialog(){const e=prompt("Enter new working directory:",this.currentWorkingDir||"");e&&""!==e.trim()&&this.setWorkingDirectory(e.trim())}showWorkingDirectoryViewer(){this.createDirectoryViewerOverlay()}createDirectoryViewerOverlay(){this.removeDirectoryViewerOverlay();const e=document.querySelector(".working-dir-display");if(!e)return;const t=document.createElement("div");t.id="directory-viewer-overlay",t.className="directory-viewer-overlay",t.innerHTML=`\n <div class="directory-viewer-content">\n <div class="directory-viewer-header">\n <h3 class="directory-viewer-title">\n ๐Ÿ“ ${this.currentWorkingDir||"Working Directory"}\n </h3>\n <button class="close-btn" onclick="workingDirectoryManager.removeDirectoryViewerOverlay()">โœ•</button>\n </div>\n <div class="directory-viewer-body">\n <div class="loading-indicator">Loading directory contents...</div>\n </div>\n <div class="directory-viewer-footer">\n <span class="directory-hint">Click file to view โ€ข Shift+Click directory path to change</span>\n </div>\n </div>\n `;const r=e.getBoundingClientRect();t.style.cssText=`\n position: fixed;\n top: ${r.bottom+5}px;\n left: ${r.left}px;\n min-width: 400px;\n max-width: 600px;\n max-height: 400px;\n z-index: 1001;\n background: white;\n border-radius: 8px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);\n border: 1px solid #e2e8f0;\n `,document.body.appendChild(t),this.loadDirectoryContents(),setTimeout(()=>{document.addEventListener("click",this.handleOutsideClick.bind(this),!0)},100)}removeDirectoryViewerOverlay(){const e=document.getElementById("directory-viewer-overlay");e&&(e.remove(),document.removeEventListener("click",this.handleOutsideClick.bind(this),!0))}handleOutsideClick(e){const t=document.getElementById("directory-viewer-overlay"),r=document.getElementById("working-dir-path");t&&!t.contains(e.target)&&e.target!==r&&this.removeDirectoryViewerOverlay()}loadDirectoryContents(){if(!this.socketManager||!this.socketManager.isConnected())return void this.showDirectoryError("Not connected to server");const e=this.socketManager.getSocket();if(!e)return void this.showDirectoryError("No socket connection available");e.emit("get_directory_listing",{directory:this.currentWorkingDir,limit:50});const t=r=>{e.off("directory_listing_response",t),this.handleDirectoryListingResponse(r)};e.on("directory_listing_response",t),setTimeout(()=>{e.off("directory_listing_response",t);const r=document.getElementById("directory-viewer-overlay");r&&r.querySelector(".loading-indicator")&&this.showDirectoryError("Request timeout")},5e3)}handleDirectoryListingResponse(e){const t=document.querySelector(".directory-viewer-body");if(!t)return;if(!e.success)return void this.showDirectoryError(e.error||"Failed to load directory");const r=e.files||[],o=e.directories||[];let i="";if(this.currentWorkingDir&&"/"!==this.currentWorkingDir){const e=this.currentWorkingDir.split("/").slice(0,-1).join("/")||"/";i+=`\n <div class="file-item directory-item" onclick="workingDirectoryManager.setWorkingDirectory('${e}')">\n <span class="file-icon">๐Ÿ“</span>\n <span class="file-name">..</span>\n <span class="file-type">parent directory</span>\n </div>\n `}o.forEach(e=>{const t=`${this.currentWorkingDir}/${e}`.replace(/\/+/g,"/");i+=`\n <div class="file-item directory-item" onclick="workingDirectoryManager.setWorkingDirectory('${t}')">\n <span class="file-icon">๐Ÿ“</span>\n <span class="file-name">${e}</span>\n <span class="file-type">directory</span>\n </div>\n `}),r.forEach(e=>{const t=`${this.currentWorkingDir}/${e}`.replace(/\/+/g,"/"),r=e.split(".").pop().toLowerCase(),o=this.getFileIcon(r);i+=`\n <div class="file-item" onclick="workingDirectoryManager.viewFile('${t}')">\n <span class="file-icon">${o}</span>\n <span class="file-name">${e}</span>\n <span class="file-type">${r}</span>\n </div>\n `}),""===i&&(i='<div class="no-files">Empty directory</div>'),t.innerHTML=i}showDirectoryError(e){const t=document.querySelector(".directory-viewer-body");t&&(t.innerHTML=`\n <div class="directory-error">\n <span class="error-icon">โš ๏ธ</span>\n <span class="error-message">${e}</span>\n </div>\n `)}getFileIcon(e){return{js:"๐Ÿ“„",py:"๐Ÿ",html:"๐ŸŒ",css:"๐ŸŽจ",json:"๐Ÿ“‹",md:"๐Ÿ“",txt:"๐Ÿ“",yml:"โš™๏ธ",yaml:"โš™๏ธ",xml:"๐Ÿ“„",pdf:"๐Ÿ“•",png:"๐Ÿ–ผ๏ธ",jpg:"๐Ÿ–ผ๏ธ",jpeg:"๐Ÿ–ผ๏ธ",gif:"๐Ÿ–ผ๏ธ",svg:"๐Ÿ–ผ๏ธ",zip:"๐Ÿ“ฆ",tar:"๐Ÿ“ฆ",gz:"๐Ÿ“ฆ",sh:"๐Ÿ”ง",bat:"๐Ÿ”ง",exe:"โš™๏ธ",dll:"โš™๏ธ"}[e]||"๐Ÿ“„"}viewFile(e){this.removeDirectoryViewerOverlay(),window.showFileViewerModal?window.showFileViewerModal(e):console.warn("File viewer modal function not available")}getCurrentWorkingDir(){return this.currentWorkingDir}getSessionDirectories(){return JSON.parse(localStorage.getItem("sessionWorkingDirs")||"{}")}setSessionDirectory(e,t){const r=this.getSessionDirectories();r[e]=t,localStorage.setItem("sessionWorkingDirs",JSON.stringify(r));const o=document.getElementById("session-select");o&&o.value===e&&this.setWorkingDirectory(t)}removeSessionDirectory(e){const t=this.getSessionDirectories();delete t[e],localStorage.setItem("sessionWorkingDirs",JSON.stringify(t))}clearAllSessionDirectories(){localStorage.removeItem("sessionWorkingDirs")}extractWorkingDirectoryFromPair(e){return e.pre?.working_dir?e.pre.working_dir:e.post?.working_dir?e.post.working_dir:e.pre?.data?.working_dir?e.pre.data.working_dir:e.post?.data?.working_dir?e.post.data.working_dir:this.currentWorkingDir||this.getDefaultWorkingDir()}validateDirectoryPath(e){if(!e||"string"!=typeof e)return!1;const t=e.trim();if(0===t.length)return!1;if(t.includes("\0"))return!1;return!["Loading...","Loading","Unknown","undefined","null","Not Connected","Invalid Directory","No Directory"].includes(t)&&(!(!t.startsWith("/")&&!/^[A-Za-z]:/.test(t))||!!(t.startsWith("./")||t.startsWith("../")||/^[a-zA-Z0-9._-]+/.test(t)))}handleGitBranchResponse(e){console.log("[GIT-BRANCH-DEBUG] handleGitBranchResponse called with:",e);const t=document.getElementById("footer-git-branch");if(t){if(e.success)console.log("[GIT-BRANCH-DEBUG] Git branch request successful, branch:",e.branch),t.textContent=e.branch,t.style.display="inline",t.classList.remove("git-error"),t.classList.add("git-success");else{let r="Git Error";const o=e.error||"Unknown error";r=o.includes("Directory not found")||o.includes("does not exist")?"Dir Not Found":o.includes("Not a directory")?"Invalid Path":o.includes("Not a git repository")?"No Git Repo":o.includes("git")?"Git Error":"Unknown",console.log("[GIT-BRANCH-DEBUG] Git branch request failed:",o,"- showing as:",r),t.textContent=r,t.style.display="inline",t.classList.remove("git-success"),t.classList.add("git-error")}e.original_working_dir&&console.log("[GIT-BRANCH-DEBUG] Server received original working_dir:",this.repr(e.original_working_dir)),e.working_dir&&console.log("[GIT-BRANCH-DEBUG] Server used working_dir:",this.repr(e.working_dir)),e.git_error&&console.log("[GIT-BRANCH-DEBUG] Git command stderr:",e.git_error)}else console.warn("[GIT-BRANCH-DEBUG] footer-git-branch element not found")}isWorkingDirectoryReady(){const e=this.getCurrentWorkingDir();return this.validateDirectoryPath(e)&&"Loading..."!==e&&"Unknown"!==e}whenDirectoryReady(e,t=5e3){const r=Date.now(),o=()=>{this.isWorkingDirectoryReady()?e():Date.now()-r<t?setTimeout(o,100):console.warn("[WORKING-DIR-DEBUG] Timeout waiting for directory to be ready")};o()}repr(e){return null===e?"null":void 0===e?"undefined":"string"==typeof e?`"${e}"`:String(e)}cleanup(){this.footerDirObserver&&(this.footerDirObserver.disconnect(),this.footerDirObserver=null),console.log("Working directory manager cleaned up")}};
2
- //# sourceMappingURL=working-directory.js.map
@@ -1,2 +0,0 @@
1
- class e{constructor(){this.eventViewer=null,this.moduleViewer=null,this.sessionManager=null,this.activityTreeRetryCount=0,this.maxRetryAttempts=10,this.socketManager=null,this.agentInference=null,this.agentHierarchy=null,this.uiStateManager=null,this.eventProcessor=null,this.exportManager=null,this.workingDirectoryManager=null,this.fileToolTracker=null,this.buildTracker=null,this.init()}init(){console.log("Initializing refactored Claude MPM Dashboard...");try{this.fetchServerConfig(),this.initializeSocketManager(),this.initializeCoreComponents(),this.initializeBuildTracker(),this.initializeAgentInference(),this.initializeAgentHierarchy(),this.initializeUIStateManager(),this.initializeWorkingDirectoryManager(),this.initializeFileToolTracker(),this.initializeEventProcessor(),this.initializeExportManager(),this.setupModuleInteractions(),this.initializeFromURL(),console.log("Claude MPM Dashboard initialized successfully")}catch(e){throw console.error("Error during dashboard initialization:",e),e}}fetchServerConfig(){fetch("/api/config").then(e=>e.json()).then(e=>{window.dashboardConfig=e;const t=document.getElementById("working-dir-path");t&&e.workingDirectory&&(t.textContent=e.workingDirectory);const n=document.getElementById("footer-git-branch");n&&e.gitBranch&&(n.textContent=e.gitBranch),console.log("Dashboard configuration loaded:",e)}).catch(e=>{console.warn("Failed to fetch server config:",e),window.dashboardConfig={workingDirectory:".",gitBranch:"Unknown"}})}validateInitialization(){const e=[{name:"socketManager",component:this.socketManager},{name:"eventViewer",component:this.eventViewer},{name:"agentHierarchy",component:this.agentHierarchy}].filter(e=>!e.component);e.length>0&&console.warn("Missing critical components:",e.map(e=>e.name))}postInit(){try{this.agentHierarchy&&(window.dashboard.agentHierarchy=this.agentHierarchy),this.validateInitialization()}catch(e){console.error("Error in dashboard postInit:",e)}}initializeSocketManager(){this.socketManager=new SocketManager,this.socketManager.setupConnectionControls(),this.socketClient=this.socketManager.getSocketClient(),window.socketClient=this.socketClient}initializeCoreComponents(){this.eventViewer=new EventViewer("events-list",this.socketClient),this.moduleViewer=new ModuleViewer,this.sessionManager=new SessionManager(this.socketClient),window.eventViewer=this.eventViewer,window.moduleViewer=this.moduleViewer,window.sessionManager=this.sessionManager}initializeBuildTracker(){this.buildTracker=new BuildTracker,this.buildTracker.setSocketClient(this.socketClient);const e=()=>{const t=document.querySelector(".header-title");t?(this.buildTracker.mount(t),console.log("BuildTracker mounted successfully")):(console.warn("Header-title element not found for build tracker, will retry"),setTimeout(e,100))};e(),window.buildTracker=this.buildTracker}initializeAgentInference(){this.agentInference=new AgentInference(this.eventViewer),this.agentInference.initialize()}initializeAgentHierarchy(){try{this.agentHierarchy=new AgentHierarchy(this.agentInference,this.eventViewer)}catch(e){console.error("Failed to initialize agent hierarchy:",e),this.agentHierarchy={render:()=>'<div class="error">Agent hierarchy unavailable</div>',expandAllNodes:()=>{},collapseAllNodes:()=>{},updateWithNewEvents:()=>{}}}}initializeUIStateManager(){this.uiStateManager=new UIStateManager,this.setupTabFilters()}initializeWorkingDirectoryManager(){this.workingDirectoryManager=new WorkingDirectoryManager(this.socketManager)}initializeFileToolTracker(){this.fileToolTracker=new FileToolTracker(this.agentInference,this.workingDirectoryManager)}initializeEventProcessor(){this.eventProcessor=new EventProcessor(this.eventViewer,this.agentInference)}initializeExportManager(){this.exportManager=new ExportManager(this.eventViewer)}setupModuleInteractions(){this.socketManager.onEventUpdate(e=>{console.log("[Dashboard] Processing event update with",e.length,"events"),e.length>0&&console.log("[Dashboard] Sample event structure:",{first_event:e[0],has_tool_events:e.some(e=>e.tool_name||e.data&&e.data.tool_name),hook_events:e.filter(e=>"hook"===e.type).length,tool_subtypes:e.filter(e=>"pre_tool"===e.subtype||"post_tool"===e.subtype).length}),this.fileToolTracker.updateFileOperations(e),this.fileToolTracker.updateToolCalls(e);const t=this.fileToolTracker.getFileOperations(),n=this.fileToolTracker.getToolCalls();console.log("[Dashboard] After update - File operations:",t.size,"Tool calls:",n.size),this.agentInference.processAgentInference(),window.CodeViewer&&"function"==typeof window.CodeViewer.refreshFromFileToolTracker&&setTimeout(()=>{window.CodeViewer.refreshFromFileToolTracker()},50),this.agentHierarchy.updateWithNewEvents(e),"events"===this.uiStateManager.getCurrentTab()&&this.exportManager.scrollListToBottom("events-list"),this.renderCurrentTab()}),this.socketManager.onConnectionStatusChange((e,t)=>{"connected"===t&&this.workingDirectoryManager.updateGitBranch(this.workingDirectoryManager.getCurrentWorkingDir())}),document.addEventListener("tabChanged",e=>{this.renderCurrentTab(),this.uiStateManager.updateTabNavigationItems()}),document.addEventListener("eventsClearing",()=>{this.fileToolTracker.clear(),this.agentInference.initialize()}),document.addEventListener("showCardDetails",e=>{this.showCardDetails(e.detail.tabName,e.detail.index)}),document.addEventListener("sessionFilterChanged",e=>{this.renderCurrentTab()})}setupTabFilters(){const e=document.getElementById("agents-search-input"),t=document.getElementById("agents-type-filter");e&&e.addEventListener("input",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),t&&t.addEventListener("change",()=>{"agents"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const n=document.getElementById("tools-search-input"),i=document.getElementById("tools-type-filter");n&&n.addEventListener("input",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),i&&i.addEventListener("change",()=>{"tools"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()});const o=document.getElementById("files-search-input"),r=document.getElementById("files-type-filter");o&&o.addEventListener("input",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()}),r&&r.addEventListener("change",()=>{"files"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()})}initializeFromURL(){const e=new URLSearchParams(window.location.search);this.socketManager.initializeFromURL(e)}renderCurrentTab(){const e=this.uiStateManager.getCurrentTab();switch(e){case"events":break;case"claude-tree":window.CodeViewer&&"function"==typeof window.CodeViewer.show&&window.CodeViewer.show();break;case"activity":if(window.ActivityTree&&"function"==typeof window.ActivityTree)this.activityTreeRetryCount=0,window.activityTreeInstance||(window.activityTreeInstance=new window.ActivityTree),window.activityTreeInstance&&(window.activityTreeInstance.initialized||window.activityTreeInstance.initialize(),"function"==typeof window.activityTreeInstance.renderWhenVisible&&window.activityTreeInstance.renderWhenVisible(),"function"==typeof window.activityTreeInstance.forceShow&&window.activityTreeInstance.forceShow());else if(window.activityTree&&"function"==typeof window.activityTree){const e=window.activityTree();e&&("function"==typeof e.renderWhenVisible&&e.renderWhenVisible(),"function"==typeof e.forceShow&&e.forceShow())}else if(this.activityTreeRetryCount<this.maxRetryAttempts)this.activityTreeRetryCount++,console.warn(`Activity tree component not available, retrying in 100ms... (attempt ${this.activityTreeRetryCount}/${this.maxRetryAttempts})`),setTimeout(()=>{"activity"===this.uiStateManager.getCurrentTab()&&this.renderCurrentTab()},100);else{console.error("Maximum retry attempts reached for ActivityTree initialization. Giving up.");const e=document.getElementById("activity-tree-container")||document.getElementById("activity-tree");e&&(e.innerHTML='<div class="error-message">โš ๏ธ Activity Tree failed to load. Please refresh the page.</div>')}break;case"agents":this.renderAgents();break;case"tools":this.renderTools();break;case"files":this.renderFiles()}this.uiStateManager.getSelectedCard().tab===e&&this.uiStateManager.updateCardSelectionUI(),this.uiStateManager.updateUnifiedSelectionUI()}renderAgents(){const e=document.getElementById("agents-list");if(!e)return;const t=document.getElementById("agents-search-input")?.value||"",n=document.getElementById("agents-type-filter")?.value||"",i=this.renderAgentsFlat(t,n);e.innerHTML=i,this.removeHierarchyControls();const o=this.agentInference.getUniqueAgentInstances();this.updateAgentsFilterDropdowns(o)}removeHierarchyControls(){const e=document.getElementById("hierarchy-controls");e&&e.remove()}renderAgentsFlat(e,t){const n=this.eventViewer.events;if(!n||0===n.length)return'<div class="no-events">No agent events found...</div>';this.agentInference.processAgentInference();const i=this.agentInference.getEventAgentMap(),o=[];if(n.forEach((n,r)=>{const s=i.get(r);if(s&&("subagent"===s.type||"main_agent"===s.type)){let i=!0;if(e){const t=e.toLowerCase();i=i&&(s.agentName.toLowerCase().includes(t)||n.tool_name&&n.tool_name.toLowerCase().includes(t)||n.data&&JSON.stringify(n.data).toLowerCase().includes(t))}t&&(i=i&&s.agentName.includes(t)),i&&o.push({event:n,inference:s,index:r,timestamp:new Date(n.timestamp)})}}),0===o.length)return'<div class="no-events">No agent events match the current filters...</div>';return`<div class="agent-events-flat">${o.map((e,t)=>{const{event:n,inference:i,index:o,timestamp:r}=e;let s="Activity",a="๐Ÿ“‹",l="";if("SubagentStart"===n.event_type)s="Started",a="๐ŸŸข",l="Agent session began";else if("SubagentStop"===n.event_type)s="Stopped",a="๐Ÿ”ด",l="Agent session ended";else if(n.tool_name&&(s=`Tool: ${n.tool_name}`,a=this.getToolIcon(n.tool_name),n.data&&n.data.tool_parameters)){const e=n.data.tool_parameters;e.file_path?l=e.file_path:e.command?l=e.command.substring(0,50)+(e.command.length>50?"...":""):e.pattern?l=`pattern="${e.pattern}"`:e.query&&(l=`query="${e.query}"`)}let c="completed";return"SubagentStart"===n.event_type?c="active":n.data&&n.data.error&&(c="error"),`\n <div class="agent-event-item" data-index="${t}" onclick="window.dashboard.showCardDetails('agents', ${o})">\n <div class="agent-event-header">\n <div class="agent-event-time">${this.formatTimestamp(r)}</div>\n <div class="agent-event-agent">\n ${this.getAgentIcon(i.agentName)} ${i.agentName}\n </div>\n <div class="agent-event-action">\n ${a} ${s}\n </div>\n <div class="agent-event-status status-${c}">\n ${this.getStatusIcon(c)}\n </div>\n </div>\n ${l?`<div class="agent-event-details">${this.escapeHtml(l)}</div>`:""}\n </div>\n `}).join("")}</div>`}getAgentIcon(e){return{PM:"๐ŸŽฏ","Engineer Agent":"๐Ÿ”ง","Research Agent":"๐Ÿ”","QA Agent":"โœ…","Documentation Agent":"๐Ÿ“","Security Agent":"๐Ÿ”’","Ops Agent":"โš™๏ธ","Version Control Agent":"๐Ÿ“ฆ","Data Engineer Agent":"๐Ÿ’พ","Test Integration Agent":"๐Ÿงช"}[e]||"๐Ÿค–"}getToolIcon(e){return{Read:"๐Ÿ“–",Write:"โœ๏ธ",Edit:"๐Ÿ“",Bash:"๐Ÿ’ป",Grep:"๐Ÿ”",Glob:"๐Ÿ“‚",LS:"๐Ÿ“",Task:"๐Ÿ“‹"}[e]||"๐Ÿ”ง"}getStatusIcon(e){return{active:"๐ŸŸข",completed:"โœ…",error:"โŒ",pending:"๐ŸŸก"}[e]||"โ“"}formatTimestamp(e){return e.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1})}escapeHtml(e){if(!e)return"";const t=document.createElement("div");return t.textContent=e,t.innerHTML}renderTools(){const e=document.getElementById("tools-list");if(!e)return;const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.getUniqueToolInstances(n),o=this.eventProcessor.generateToolHTML(i);e.innerHTML=o,this.exportManager.scrollListToBottom("tools-list"),this.updateToolsFilterDropdowns(i)}renderFiles(){const e=document.getElementById("files-list");if(!e)return;const t=this.fileToolTracker.getFileOperations(),n=Array.from(t.entries());console.log("[renderFiles] File operations map size:",t.size),console.log("[renderFiles] Files array:",n);const i=this.eventProcessor.getUniqueFileInstances(n),o=this.eventProcessor.generateFileHTML(i);0===n.length?e.innerHTML='<div class="empty-state">No file operations tracked yet. File operations will appear here when tools like Read, Write, Edit, or Grep are used.</div>':e.innerHTML=o,this.exportManager.scrollListToBottom("files-list"),this.updateFilesFilterDropdowns(n)}updateAgentsFilterDropdowns(e){const t=new Set;e.forEach(e=>{e.agentName&&"Unknown"!==e.agentName&&t.add(e.agentName)});const n=Array.from(t).filter(e=>e&&""!==e.trim());this.populateFilterDropdown("agents-type-filter",n,"All Agent Types")}updateToolsFilterDropdowns(e){const t=[...new Set(e.map(([e,t])=>t.tool_name))].filter(e=>e);this.populateFilterDropdown("tools-type-filter",t,"All Tools")}updateFilesFilterDropdowns(e){const t=[...new Set(e.flatMap(([e,t])=>t.operations.map(e=>e.operation)))].filter(e=>e);this.populateFilterDropdown("files-type-filter",t,"All Operations")}populateFilterDropdown(e,t,n="All"){const i=document.getElementById(e);if(!i)return;const o=i.value,r=t.sort((e,t)=>e.localeCompare(t));i.innerHTML=`<option value="">${n}</option>`,r.forEach(e=>{const t=document.createElement("option");t.value=e,t.textContent=e,i.appendChild(t)}),o&&r.includes(o)&&(i.value=o)}showCardDetails(e,t){switch(e){case"events":this.eventViewer&&this.eventViewer.showEventDetails(t);break;case"agents":this.showAgentDetailsByIndex(t);break;case"tools":this.showToolDetailsByIndex(t);break;case"files":this.showFileDetailsByIndex(t)}}showAgentDetailsByIndex(e){const t=this.eventProcessor.getFilteredEventsForTab("agents");if(!t||!Array.isArray(t)||e<0||e>=t.length)return void console.warn("Dashboard: Invalid agent index or events array");const n=this.eventProcessor.applyAgentsFilters([t[e]]);if(n.length>0&&this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentEvent){const t=n[0];this.moduleViewer.showAgentEvent(t,e)}}showAgentInstanceDetails(e){const t=this.agentInference.getPMDelegations().get(e);if(!t){const t=this.agentInference.getUniqueAgentInstances().find(t=>t.id===e);return t?void this.showImpliedAgentDetails(t):void console.error("Agent instance not found:",e)}this.moduleViewer&&"function"==typeof this.moduleViewer.showAgentInstance?this.moduleViewer.showAgentInstance(t):console.log("Agent Instance Details:",{id:e,agentName:t.agentName,type:"PM Delegation",eventCount:t.agentEvents.length,startTime:t.timestamp,pmCall:t.pmCall})}showImpliedAgentDetails(e){this.moduleViewer&&"function"==typeof this.moduleViewer.showImpliedAgent?this.moduleViewer.showImpliedAgent(e):console.log("Implied Agent Details:",{id:e.id,agentName:e.agentName,type:"Implied PM Delegation",eventCount:e.eventCount,startTime:e.timestamp,note:"No explicit PM call found - inferred from agent activity"})}showToolDetailsByIndex(e){const t=this.fileToolTracker.getToolCalls(),n=Array.from(t.entries()),i=this.eventProcessor.applyToolCallFilters(n);if(e>=0&&e<i.length){const[t]=i[e];this.showToolCallDetails(t)}}showFileDetailsByIndex(e){const t=this.fileToolTracker.getFileOperations();let n=Array.from(t.entries());if(n=this.eventProcessor.applyFilesFilters(n),e>=0&&e<n.length){const[t]=n[e];this.showFileDetails(t)}}showToolCallDetails(e){const t=this.fileToolTracker.getToolCall(e);t&&this.moduleViewer&&this.moduleViewer.showToolCall(t,e)}showFileDetails(e){const t=this.fileToolTracker.getFileOperationsForFile(e);t&&this.moduleViewer&&this.moduleViewer.showFileOperations(t,e)}switchTab(e){this.uiStateManager.switchTab(e)}selectCard(e,t,n,i){this.uiStateManager.selectCard(e,t,n,i)}clearEvents(){this.exportManager.clearEvents()}exportEvents(){this.exportManager.exportEvents()}clearSelection(){this.uiStateManager.clearSelection(),this.eventViewer&&this.eventViewer.clearSelection(),this.moduleViewer&&this.moduleViewer.clear()}get currentWorkingDir(){return this.workingDirectoryManager.getCurrentWorkingDir()}set currentWorkingDir(e){this.workingDirectoryManager.setWorkingDirectory(e)}get currentTab(){return this.uiStateManager.getCurrentTab()}get selectedCard(){return this.uiStateManager.getSelectedCard()}get fileOperations(){return this.fileToolTracker.getFileOperations()}get toolCalls(){return this.fileToolTracker.getToolCalls()}get tabNavigation(){return this.uiStateManager?this.uiStateManager.tabNavigation:null}}async function t(e,t,i){const o=e.querySelector(".file-viewer-file-path"),r=e.querySelector(".file-viewer-file-size");o&&(o.textContent=t),r&&(r.textContent="");const s=e.querySelector(".file-viewer-loading"),a=e.querySelector(".file-viewer-error"),l=e.querySelector(".file-viewer-content-area");s&&(s.style.display="flex"),a&&(a.style.display="none"),l&&(l.style.display="none");try{const o=window.socket||window.dashboard?.socketClient?.socket||window.socketClient?.socket;if(console.log("[FileViewer] Socket search results:",{"window.socket":!!window.socket,"window.socket.connected":window.socket?.connected,"dashboard.socketClient.socket":!!window.dashboard?.socketClient?.socket,"dashboard.socketClient.socket.connected":window.dashboard?.socketClient?.socket?.connected,"window.socketClient.socket":!!window.socketClient?.socket,"window.socketClient.socket.connected":window.socketClient?.socket?.connected}),!o)throw new Error("No socket connection available. Please ensure the dashboard is connected.");o.connected||console.warn("[FileViewer] Socket found but not connected, attempting to use anyway..."),console.log("[FileViewer] Socket found, setting up listener for file_content_response");const r=new Promise((e,n)=>{const i=r=>{console.log("[FileViewer] Received file_content_response:",r),r.file_path===t&&(o.off("file_content_response",i),r.success?(console.log("[FileViewer] File content loaded successfully"),e(r)):(console.error("[FileViewer] File read failed:",r.error),n(new Error(r.error||"Failed to read file"))))};o.on("file_content_response",i),console.log("[FileViewer] Listener registered for file_content_response"),setTimeout(()=>{o.off("file_content_response",i),console.error("[FileViewer] Request timeout after 10 seconds"),n(new Error("Request timeout - server did not respond"))},1e4)}),s={file_path:t,working_dir:i};console.log("[FileViewer] Emitting read_file event with data:",s),o.emit("read_file",s);const a=await r,l=e.querySelector(".file-viewer-loading");l&&(l.style.display="none"),function(e,t){const i=e.querySelector(".file-viewer-content-area"),o=e.querySelector(".file-extension"),r=e.querySelector(".file-encoding"),s=e.querySelector(".file-viewer-file-size"),a=e.querySelector(".file-content-code");o&&(o.textContent=`Type: ${t.extension||"unknown"}`);r&&(r.textContent=`Encoding: ${t.encoding||"unknown"}`);s&&(s.textContent=`Size: ${function(e){if(!e)return"0 B";const t=1024,n=["B","KB","MB","GB"],i=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/Math.pow(t,i)).toFixed(2))+" "+n[i]}(t.file_size)}`);if(a&&t.content){a.innerHTML=function(e,t){const i=e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");switch(t){case".js":case".jsx":case".ts":case".tsx":return function(e){return n(e.replace(/\b(function|const|let|var|if|else|for|while|return|import|export|class|extends)\b/g,'<span class="keyword">$1</span>').replace(/(\/\*[\s\S]*?\*\/|\/\/.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|`[^`]*`)/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(i);case".py":return function(e){return n(e.replace(/\b(def|class|if|elif|else|for|while|return|import|from|as|try|except|finally|with)\b/g,'<span class="keyword">$1</span>').replace(/(#.*)/g,'<span class="comment">$1</span>').replace(/('[^']*'|"[^"]*"|"""[\s\S]*?""")/g,'<span class="string">$1</span>').replace(/\b(\d+)\b/g,'<span class="number">$1</span>'))}(i);case".json":return function(e){return n(e.replace(/("[\w\s]*")\s*:/g,'<span class="property">$1</span>:').replace(/:\s*(".*?")/g,': <span class="string">$1</span>').replace(/:\s*(\d+)/g,': <span class="number">$1</span>').replace(/:\s*(true|false|null)/g,': <span class="keyword">$1</span>'))}(i);case".css":return function(e){return n(e.replace(/([.#]?[\w-]+)\s*\{/g,'<span class="selector">$1</span> {').replace(/([\w-]+)\s*:/g,'<span class="property">$1</span>:').replace(/:\s*([^;]+);/g,': <span class="value">$1</span>;').replace(/(\/\*[\s\S]*?\*\/)/g,'<span class="comment">$1</span>'))}(i);case".html":case".htm":return function(e){return n(e.replace(/(&lt;\/?[\w-]+)/g,'<span class="tag">$1</span>').replace(/([\w-]+)=(['"][^'"]*['"])/g,'<span class="attribute">$1</span>=<span class="string">$2</span>').replace(/(&lt;!--[\s\S]*?--&gt;)/g,'<span class="comment">$1</span>'))}(i);case".md":case".markdown":return function(e){return n(e.replace(/^(#{1,6})\s+(.*)$/gm,'<span class="header">$1</span> <span class="header-text">$2</span>').replace(/\*\*(.*?)\*\*/g,'<span class="bold">**$1**</span>').replace(/\*(.*?)\*/g,'<span class="italic">*$1*</span>').replace(/`([^`]+)`/g,'<span class="code">`$1`</span>').replace(/^\s*[-*+]\s+(.*)$/gm,'<span class="list-marker">โ€ข</span> $1'))}(i);default:return n(i)}}(t.content,t.extension);const i=e.querySelector(".file-viewer-scroll-wrapper");i&&setTimeout(()=>{const t=e.querySelector(".modal-content"),n=e.querySelector(".file-viewer-header"),o=e.querySelector(".file-viewer-toolbar"),r=(t?.offsetHeight||0)-(n?.offsetHeight||0)-(o?.offsetHeight||0)-40;i.style.maxHeight=`${r}px`,i.style.overflowY="auto"},50)}else console.warn("โš ๏ธ Missing codeElement or file content");i&&(i.style.display="block")}(e,a)}catch(c){console.error("โŒ Failed to fetch file content:",c);const n=e.querySelector(".file-viewer-loading");n&&(n.style.display="none");let o=c.message||"Unknown error occurred",r=[];c.message.includes("No socket connection")?(o="Failed to connect to the monitoring server",r=["Check if the monitoring server is running","Verify the socket connection in the dashboard","Try refreshing the page and reconnecting"]):c.message.includes("timeout")?(o="Request timed out",r=["The file may be too large to load quickly","Check your network connection","Try again in a few moments"]):c.message.includes("File does not exist")?(o="File not found",r=["The file may have been moved or deleted","Check the file path spelling","Refresh the file list to see current files"]):c.message.includes("Access denied")&&(o="Access denied",r=["The file is outside the allowed directories","File access is restricted for security reasons"]),function(e,t){const n=e.querySelector(".file-viewer-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions");let r=t.error||"Unknown error occurred";i&&(i.innerHTML=`\n <div class="error-main">${r}</div>\n ${t.file_path?`<div class="error-file">File: ${t.file_path}</div>`:""}\n ${t.working_dir?`<div class="error-dir">Working directory: ${t.working_dir}</div>`:""}\n `);o&&(t.suggestions&&t.suggestions.length>0?o.innerHTML=`\n <h4>Suggestions:</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `:o.innerHTML="");console.log("๐Ÿ“‹ Displaying file viewer error:",{originalError:t.error,processedMessage:r,suggestions:t.suggestions}),n&&(n.style.display="block")}(e,{error:o,file_path:t,working_dir:i,suggestions:r})}}function n(e){return e.split("\n").map((e,t)=>`<span class="line-number">${String(t+1).padStart(3," ")}</span> ${e||" "}`).join("\n")}function i(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}window.clearEvents=function(){window.dashboard&&window.dashboard.clearEvents()},window.exportEvents=function(){window.dashboard&&window.dashboard.exportEvents()},window.clearSelection=function(){window.dashboard&&window.dashboard.clearSelection()},window.switchTab=function(e){window.dashboard&&window.dashboard.switchTab(e)},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy");if(t){const e=t.textContent;t.textContent="โœ… Copied!",setTimeout(()=>{t.textContent=e},2e3)}}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy");if(i){const e=i.textContent;i.textContent="โœ… Copied!",setTimeout(()=>{i.textContent=e},2e3)}}},window.showFileViewerModal=async function(e){console.log("[FileViewer] Opening file:",e);let n="";window.dashboard&&window.dashboard.currentWorkingDir&&(n=window.dashboard.currentWorkingDir,console.log("[FileViewer] Using working directory:",n));let i=document.getElementById("file-viewer-modal");i||(console.log("[FileViewer] Creating new modal"),i=function(){const e=document.createElement("div");return e.id="file-viewer-modal",e.className="modal file-viewer-modal",e.innerHTML='\n <div class="modal-content file-viewer-content">\n <div class="file-viewer-header">\n <h2 class="file-viewer-title">\n <span class="file-viewer-icon">๐Ÿ“„</span>\n <span class="file-viewer-title-text">File Viewer</span>\n </h2>\n <div class="file-viewer-meta">\n <span class="file-viewer-file-path"></span>\n <span class="file-viewer-file-size"></span>\n </div>\n <button class="file-viewer-close" onclick="hideFileViewerModal()">\n <span>&times;</span>\n </button>\n </div>\n <div class="file-viewer-body">\n <div class="file-viewer-loading">\n <div class="loading-spinner"></div>\n <span>Loading file content...</span>\n </div>\n <div class="file-viewer-error" style="display: none;">\n <div class="error-icon">โš ๏ธ</div>\n <div class="error-message"></div>\n <div class="error-suggestions"></div>\n </div>\n <div class="file-viewer-content-area" style="display: none;">\n <div class="file-viewer-toolbar">\n <div class="file-viewer-info">\n <span class="file-extension"></span>\n <span class="file-encoding"></span>\n </div>\n <div class="file-viewer-actions">\n <button class="file-content-copy" onclick="copyFileContent()">\n ๐Ÿ“‹ Copy\n </button>\n </div>\n </div>\n <div class="file-viewer-scroll-wrapper">\n <pre class="file-content-display"><code class="file-content-code"></code></pre>\n </div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideFileViewerModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideFileViewerModal()}),e}(),document.body.appendChild(i),await new Promise(e=>setTimeout(e,10))),i.style.display="flex",document.body.style.overflow="hidden",t(i,e,n).catch(e=>{console.error("Error updating file viewer modal:",e),function(e,t){const n=e.querySelector(".file-viewer-error"),i=e.querySelector(".error-message"),o=e.querySelector(".error-suggestions"),r=e.querySelector(".file-viewer-loading"),s=e.querySelector(".file-viewer-content-area");r&&(r.style.display="none");s&&(s.style.display="none");n&&(n.style.display="flex");let a=t.error||"Unknown error occurred";a.includes("not found")?a="๐Ÿ“ File not found or not accessible":a.includes("permission")?a="๐Ÿ”’ Permission denied accessing this file":a.includes("too large")?a="๐Ÿ“ File is too large to display":a.includes("socket connection")?a="๐Ÿ”Œ Not connected to the server. Please check your connection.":a.includes("timeout")?a="โฑ๏ธ Request timed out. The server may be busy or unresponsive.":a.includes("๐Ÿ“")||a.includes("๐Ÿ”’")||a.includes("๐Ÿ“")||(a=`โš ๏ธ ${a}`);i&&(i.textContent=a);o&&(t.suggestions&&t.suggestions.length>0?o.innerHTML=`\n <h4>Suggestions:</h4>\n <ul>\n ${t.suggestions.map(e=>`<li>${e}</li>`).join("")}\n </ul>\n `:o.innerHTML="\n <h4>Try:</h4>\n <ul>\n <li>Check if the file exists and is readable</li>\n <li>Verify file permissions</li>\n <li>Ensure the monitoring server has access to this file</li>\n </ul>\n ");console.log("๐Ÿ“‹ Displaying file content error:",{originalError:t.error,processedMessage:a,suggestions:t.suggestions}),n&&(n.style.display="block")}(i,{error:e.message})})},window.hideFileViewerModal=function(){const e=document.getElementById("file-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.copyFileContent=function(){const e=document.getElementById("file-viewer-modal");if(!e)return;const t=e.querySelector(".file-content-code");if(!t)return;const n=t.textContent;if(navigator.clipboard&&navigator.clipboard.writeText)navigator.clipboard.writeText(n).then(()=>{const t=e.querySelector(".file-content-copy");if(t){const e=t.textContent;t.textContent="โœ… Copied!",setTimeout(()=>{t.textContent=e},2e3)}}).catch(e=>{console.error("Failed to copy text:",e)});else{const t=document.createElement("textarea");t.value=n,document.body.appendChild(t),t.select(),document.execCommand("copy"),document.body.removeChild(t);const i=e.querySelector(".file-content-copy");if(i){const e=i.textContent;i.textContent="โœ… Copied!",setTimeout(()=>{i.textContent=e},2e3)}}},window.showSearchViewerModal=function(e,t){let n=document.getElementById("search-viewer-modal");n||(n=function(){const e=document.createElement("div");return e.id="search-viewer-modal",e.className="modal search-viewer-modal",e.innerHTML='\n <div class="modal-content search-viewer-content">\n <div class="search-viewer-header">\n <h2 class="search-viewer-title">\n <span class="search-viewer-icon">๐Ÿ”</span>\n <span class="search-viewer-title-text">Search Results</span>\n </h2>\n <button class="search-viewer-close" onclick="hideSearchViewerModal()">\n <span>&times;</span>\n </button>\n </div>\n <div class="search-viewer-body">\n <div class="search-params-section">\n <h3>Search Parameters</h3>\n <pre class="search-params-display"></pre>\n </div>\n <div class="search-results-section">\n <h3>Search Results</h3>\n <div class="search-results-display"></div>\n </div>\n </div>\n </div>\n ',e.addEventListener("click",t=>{t.target===e&&hideSearchViewerModal()}),document.addEventListener("keydown",t=>{"Escape"===t.key&&"flex"===e.style.display&&hideSearchViewerModal()}),e}(),document.body.appendChild(n)),function(e,t,n){const o=e.querySelector(".search-params-display"),r=e.querySelector(".search-results-display");o&&t&&(o.textContent=JSON.stringify(t,null,2));if(r&&n){let e="";"string"==typeof n?e=`<pre class="search-results-text">${i(n)}</pre>`:Array.isArray(n)?(e='<ul class="search-results-list">',n.forEach(t=>{e+="object"==typeof t?`<li><pre>${JSON.stringify(t,null,2)}</pre></li>`:`<li>${i(String(t))}</li>`}),e+="</ul>"):e="object"==typeof n?`<pre class="search-results-json">${JSON.stringify(n,null,2)}</pre>`:`<div class="search-results-text">${i(String(n))}</div>`,r.innerHTML=e}}(n,e,t),n.style.display="flex",document.body.style.overflow="hidden"},window.hideSearchViewerModal=function(){const e=document.getElementById("search-viewer-modal");e&&(e.style.display="none",document.body.style.overflow="")},window.showAgentInstanceDetails=function(e){window.dashboard&&"function"==typeof window.dashboard.showAgentInstanceDetails?window.dashboard.showAgentInstanceDetails(e):console.error("Dashboard not available or method not found")},document.addEventListener("DOMContentLoaded",function(){try{window.dashboard=new e,window.dashboard&&"function"==typeof window.dashboard.postInit&&window.dashboard.postInit(),console.log("Dashboard loaded and initialized successfully"),document.dispatchEvent(new CustomEvent("dashboardReady",{detail:{dashboard:window.dashboard}}))}catch(t){console.error("Failed to initialize dashboard:",t),document.body.innerHTML=`\n <div style="padding: 20px; font-family: sans-serif;">\n <h1>Dashboard Initialization Error</h1>\n <p>The dashboard failed to load properly. Please refresh the page or check the console for details.</p>\n <pre style="background: #f5f5f5; padding: 10px; border-radius: 4px;">${t.message}</pre>\n </div>\n `}});
2
- //# sourceMappingURL=dashboard.js.map