claude-mpm 4.16.0__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 (531) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  3. claude_mpm/agents/BASE_PM.md +272 -23
  4. claude_mpm/agents/OUTPUT_STYLE.md +3 -48
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +1821 -32
  6. claude_mpm/agents/WORKFLOW.md +75 -2
  7. claude_mpm/agents/agent_loader.py +4 -4
  8. claude_mpm/agents/base_agent.json +6 -3
  9. claude_mpm/agents/frontmatter_validator.py +1 -1
  10. claude_mpm/agents/templates/api_qa.json +5 -2
  11. claude_mpm/agents/templates/circuit_breakers.md +108 -2
  12. claude_mpm/agents/templates/documentation.json +33 -6
  13. claude_mpm/agents/templates/engineer.json +5 -1
  14. claude_mpm/agents/templates/javascript_engineer_agent.json +380 -0
  15. claude_mpm/agents/templates/php-engineer.json +10 -4
  16. claude_mpm/agents/templates/pm_red_flags.md +89 -19
  17. claude_mpm/agents/templates/project_organizer.json +7 -3
  18. claude_mpm/agents/templates/python_engineer.json +8 -3
  19. claude_mpm/agents/templates/qa.json +2 -1
  20. claude_mpm/agents/templates/react_engineer.json +1 -0
  21. claude_mpm/agents/templates/research.json +82 -12
  22. claude_mpm/agents/templates/rust_engineer.json +12 -7
  23. claude_mpm/agents/templates/security.json +4 -4
  24. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  25. claude_mpm/agents/templates/tauri_engineer.json +274 -0
  26. claude_mpm/agents/templates/ticketing.json +10 -6
  27. claude_mpm/agents/templates/version_control.json +4 -2
  28. claude_mpm/agents/templates/web_qa.json +2 -1
  29. claude_mpm/cli/README.md +253 -0
  30. claude_mpm/cli/__init__.py +11 -1
  31. claude_mpm/cli/commands/__init__.py +2 -0
  32. claude_mpm/cli/commands/aggregate.py +1 -1
  33. claude_mpm/cli/commands/analyze.py +3 -3
  34. claude_mpm/cli/commands/cleanup.py +1 -1
  35. claude_mpm/cli/commands/configure_agent_display.py +4 -4
  36. claude_mpm/cli/commands/debug.py +12 -12
  37. claude_mpm/cli/commands/hook_errors.py +277 -0
  38. claude_mpm/cli/commands/mcp_install_commands.py +1 -1
  39. claude_mpm/cli/commands/mcp_install_commands.py.backup +284 -0
  40. claude_mpm/cli/commands/mpm_init/README.md +365 -0
  41. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  42. claude_mpm/cli/commands/mpm_init/core.py +573 -0
  43. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  44. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  45. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  46. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  47. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  48. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  49. claude_mpm/cli/commands/run.py +124 -128
  50. claude_mpm/cli/commands/skills.py +922 -0
  51. claude_mpm/cli/executor.py +58 -0
  52. claude_mpm/cli/interactive/agent_wizard.py +5 -5
  53. claude_mpm/cli/parsers/base_parser.py +35 -0
  54. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  55. claude_mpm/cli/parsers/skills_parser.py +275 -0
  56. claude_mpm/cli/startup.py +168 -8
  57. claude_mpm/cli/startup_display.py +480 -0
  58. claude_mpm/cli/utils.py +1 -1
  59. claude_mpm/cli_module/commands.py +1 -1
  60. claude_mpm/cli_module/refactoring_guide.md +253 -0
  61. claude_mpm/commands/mpm-auto-configure.md +52 -0
  62. claude_mpm/commands/mpm-help.md +6 -0
  63. claude_mpm/commands/mpm-init.md +130 -8
  64. claude_mpm/commands/mpm-resume.md +372 -0
  65. claude_mpm/commands/mpm-tickets.md +56 -7
  66. claude_mpm/commands/mpm-version.md +113 -0
  67. claude_mpm/commands/mpm.md +2 -0
  68. claude_mpm/config/agent_capabilities.yaml +658 -0
  69. claude_mpm/config/agent_config.py +2 -2
  70. claude_mpm/config/async_logging_config.yaml +145 -0
  71. claude_mpm/constants.py +24 -0
  72. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +34 -0
  73. claude_mpm/core/api_validator.py +1 -1
  74. claude_mpm/core/claude_runner.py +14 -1
  75. claude_mpm/core/config.py +50 -0
  76. claude_mpm/core/constants.py +1 -1
  77. claude_mpm/core/factories.py +1 -1
  78. claude_mpm/core/framework/processors/metadata_processor.py +1 -1
  79. claude_mpm/core/hook_error_memory.py +381 -0
  80. claude_mpm/core/hook_manager.py +41 -2
  81. claude_mpm/core/interactive_session.py +48 -3
  82. claude_mpm/core/interfaces.py +56 -1
  83. claude_mpm/core/logger.py +3 -1
  84. claude_mpm/core/oneshot_session.py +39 -0
  85. claude_mpm/core/optimized_agent_loader.py +3 -3
  86. claude_mpm/d2/.gitignore +22 -0
  87. claude_mpm/d2/ARCHITECTURE_COMPARISON.md +273 -0
  88. claude_mpm/d2/FLASK_INTEGRATION.md +156 -0
  89. claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +452 -0
  90. claude_mpm/d2/QUICKSTART.md +186 -0
  91. claude_mpm/d2/README.md +232 -0
  92. claude_mpm/d2/STORE_FIX_SUMMARY.md +167 -0
  93. claude_mpm/d2/SVELTE5_STORES_GUIDE.md +180 -0
  94. claude_mpm/d2/TESTING.md +288 -0
  95. claude_mpm/d2/index.html +118 -0
  96. claude_mpm/d2/package.json +19 -0
  97. claude_mpm/d2/src/App.svelte +110 -0
  98. claude_mpm/d2/src/components/Header.svelte +153 -0
  99. claude_mpm/d2/src/components/MainContent.svelte +74 -0
  100. claude_mpm/d2/src/components/Sidebar.svelte +85 -0
  101. claude_mpm/d2/src/components/tabs/EventsTab.svelte +326 -0
  102. claude_mpm/d2/src/lib/socketio.js +144 -0
  103. claude_mpm/d2/src/main.js +7 -0
  104. claude_mpm/d2/src/stores/events.js +114 -0
  105. claude_mpm/d2/src/stores/socket.js +108 -0
  106. claude_mpm/d2/src/stores/theme.js +65 -0
  107. claude_mpm/d2/svelte.config.js +12 -0
  108. claude_mpm/d2/vite.config.js +15 -0
  109. claude_mpm/dashboard/.claude-mpm/memories/README.md +36 -0
  110. claude_mpm/dashboard/BUILD_NUMBER +1 -0
  111. claude_mpm/dashboard/README.md +121 -0
  112. claude_mpm/dashboard/VERSION +1 -0
  113. claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +273 -0
  114. claude_mpm/dashboard/react/components/ErrorBoundary.tsx +75 -0
  115. claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +141 -0
  116. claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +36 -0
  117. claude_mpm/dashboard/react/components/shared/FilterBar.tsx +89 -0
  118. claude_mpm/dashboard/react/contexts/DashboardContext.tsx +215 -0
  119. claude_mpm/dashboard/react/entries/events.tsx +165 -0
  120. claude_mpm/dashboard/react/hooks/useEvents.ts +191 -0
  121. claude_mpm/dashboard/react/hooks/useSocket.ts +225 -0
  122. claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +170 -0
  123. claude_mpm/dashboard/static/built/components/activity-tree.js.map +1 -0
  124. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +101 -101
  125. claude_mpm/dashboard/static/built/components/agent-inference.js.map +1 -0
  126. claude_mpm/dashboard/static/built/components/build-tracker.js +59 -59
  127. claude_mpm/dashboard/static/built/components/code-simple.js +107 -107
  128. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +29 -29
  129. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +24 -24
  130. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +27 -27
  131. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +25 -25
  132. claude_mpm/dashboard/static/built/components/code-tree.js.map +1 -0
  133. claude_mpm/dashboard/static/built/components/code-viewer.js.map +1 -0
  134. claude_mpm/dashboard/static/built/components/connection-debug.js +101 -101
  135. claude_mpm/dashboard/static/built/components/diff-viewer.js +113 -113
  136. claude_mpm/dashboard/static/built/components/event-processor.js.map +1 -0
  137. claude_mpm/dashboard/static/built/components/event-viewer.js.map +1 -0
  138. claude_mpm/dashboard/static/built/components/export-manager.js.map +1 -0
  139. claude_mpm/dashboard/static/built/components/file-change-tracker.js +57 -57
  140. claude_mpm/dashboard/static/built/components/file-change-viewer.js +74 -74
  141. claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +1 -0
  142. claude_mpm/dashboard/static/built/components/file-viewer.js.map +1 -0
  143. claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +1 -0
  144. claude_mpm/dashboard/static/built/components/hud-manager.js.map +1 -0
  145. claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +1 -0
  146. claude_mpm/dashboard/static/built/components/module-viewer.js.map +1 -0
  147. claude_mpm/dashboard/static/built/components/session-manager.js.map +1 -0
  148. claude_mpm/dashboard/static/built/components/socket-manager.js.map +1 -0
  149. claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +1 -0
  150. claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +1 -0
  151. claude_mpm/dashboard/static/built/components/working-directory.js.map +1 -0
  152. claude_mpm/dashboard/static/built/connection-manager.js +76 -76
  153. claude_mpm/dashboard/static/built/dashboard.js.map +1 -0
  154. claude_mpm/dashboard/static/built/extension-error-handler.js +22 -22
  155. claude_mpm/dashboard/static/built/react/events.js.map +1 -0
  156. claude_mpm/dashboard/static/built/shared/dom-helpers.js +9 -9
  157. claude_mpm/dashboard/static/built/shared/event-bus.js +5 -5
  158. claude_mpm/dashboard/static/built/shared/logger.js +16 -16
  159. claude_mpm/dashboard/static/built/shared/tooltip-service.js +6 -6
  160. claude_mpm/dashboard/static/built/socket-client.js.map +1 -0
  161. claude_mpm/dashboard/static/css/activity.css +69 -69
  162. claude_mpm/dashboard/static/css/connection-status.css +10 -10
  163. claude_mpm/dashboard/static/css/dashboard.css +15 -15
  164. claude_mpm/dashboard/static/index.html +22 -22
  165. claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +170 -0
  166. claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
  167. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
  168. claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
  169. claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
  170. claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
  171. claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
  172. claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
  173. claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
  174. claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
  175. claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
  176. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
  177. claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
  178. claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
  179. claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
  180. claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
  181. claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
  182. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
  183. claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
  184. claude_mpm/dashboard/static/js/connection-manager.js +76 -76
  185. claude_mpm/dashboard/static/js/dashboard.js +76 -58
  186. claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
  187. claude_mpm/dashboard/static/js/shared/dom-helpers.js +9 -9
  188. claude_mpm/dashboard/static/js/shared/event-bus.js +5 -5
  189. claude_mpm/dashboard/static/js/shared/logger.js +16 -16
  190. claude_mpm/dashboard/static/js/shared/tooltip-service.js +6 -6
  191. claude_mpm/dashboard/static/js/socket-client.js +138 -121
  192. claude_mpm/dashboard/static/navigation-test-results.md +118 -0
  193. claude_mpm/dashboard/static/production/main.html +21 -21
  194. claude_mpm/dashboard/static/test-archive/dashboard.html +22 -22
  195. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +36 -0
  196. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +39 -0
  197. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +38 -0
  198. claude_mpm/dashboard/templates/code_simple.html +23 -23
  199. claude_mpm/dashboard/templates/index.html +18 -18
  200. claude_mpm/hooks/README.md +143 -0
  201. claude_mpm/hooks/__init__.py +8 -0
  202. claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
  203. claude_mpm/hooks/claude_hooks/hook_handler.py +24 -7
  204. claude_mpm/hooks/claude_hooks/installer.py +45 -0
  205. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  206. claude_mpm/hooks/session_resume_hook.py +121 -0
  207. claude_mpm/hooks/templates/README.md +180 -0
  208. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  209. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  210. claude_mpm/hooks/templates/settings.json.example +147 -0
  211. claude_mpm/models/resume_log.py +340 -0
  212. claude_mpm/schemas/agent_schema.json +596 -0
  213. claude_mpm/schemas/frontmatter_schema.json +165 -0
  214. claude_mpm/scripts/claude-hook-handler.sh +3 -3
  215. claude_mpm/scripts/start_activity_logging.py +3 -1
  216. claude_mpm/services/agents/auto_config_manager.py +1 -1
  217. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  218. claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
  219. claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
  220. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  221. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  222. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  223. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
  224. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  225. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
  226. claude_mpm/services/agents/loading/framework_agent_loader.py +8 -8
  227. claude_mpm/services/agents/local_template_manager.py +4 -2
  228. claude_mpm/services/agents/recommender.py +47 -0
  229. claude_mpm/services/cli/resume_service.py +617 -0
  230. claude_mpm/services/cli/session_manager.py +87 -0
  231. claude_mpm/services/cli/session_pause_manager.py +504 -0
  232. claude_mpm/services/cli/session_resume_helper.py +372 -0
  233. claude_mpm/services/cli/unified_dashboard_manager.py +1 -1
  234. claude_mpm/services/core/base.py +26 -11
  235. claude_mpm/services/core/interfaces.py +56 -1
  236. claude_mpm/services/core/models/agent_config.py +3 -0
  237. claude_mpm/services/core/models/process.py +4 -0
  238. claude_mpm/services/core/path_resolver.py +1 -1
  239. claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
  240. claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
  241. claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
  242. claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
  243. claude_mpm/services/diagnostics/doctor_reporter.py +6 -4
  244. claude_mpm/services/diagnostics/models.py +21 -0
  245. claude_mpm/services/event_bus/README.md +244 -0
  246. claude_mpm/services/event_bus/direct_relay.py +3 -3
  247. claude_mpm/services/event_bus/event_bus.py +36 -3
  248. claude_mpm/services/event_bus/relay.py +23 -7
  249. claude_mpm/services/events/README.md +303 -0
  250. claude_mpm/services/events/consumers/logging.py +1 -2
  251. claude_mpm/services/framework_claude_md_generator/README.md +119 -0
  252. claude_mpm/services/infrastructure/monitoring/resources.py +1 -1
  253. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  254. claude_mpm/services/local_ops/__init__.py +2 -0
  255. claude_mpm/services/local_ops/process_manager.py +1 -1
  256. claude_mpm/services/local_ops/resource_monitor.py +2 -2
  257. claude_mpm/services/mcp_config_manager.py +7 -131
  258. claude_mpm/services/mcp_gateway/README.md +185 -0
  259. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  260. claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
  261. claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
  262. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
  263. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
  264. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  265. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
  266. claude_mpm/services/memory/failure_tracker.py +19 -4
  267. claude_mpm/services/memory/optimizer.py +1 -1
  268. claude_mpm/services/model/model_router.py +8 -9
  269. claude_mpm/services/monitor/daemon.py +1 -1
  270. claude_mpm/services/monitor/server.py +2 -2
  271. claude_mpm/services/native_agent_converter.py +356 -0
  272. claude_mpm/services/port_manager.py +1 -1
  273. claude_mpm/services/project/documentation_manager.py +2 -1
  274. claude_mpm/services/project/toolchain_analyzer.py +3 -1
  275. claude_mpm/services/runner_configuration_service.py +1 -0
  276. claude_mpm/services/self_upgrade_service.py +165 -7
  277. claude_mpm/services/session_manager.py +205 -1
  278. claude_mpm/services/skills_config.py +547 -0
  279. claude_mpm/services/skills_deployer.py +955 -0
  280. claude_mpm/services/socketio/handlers/connection.py +1 -1
  281. claude_mpm/services/socketio/handlers/connection.py.backup +217 -0
  282. claude_mpm/services/socketio/handlers/git.py +2 -2
  283. claude_mpm/services/socketio/handlers/hook.py.backup +154 -0
  284. claude_mpm/services/static/.gitkeep +2 -0
  285. claude_mpm/services/system_instructions_service.py +1 -3
  286. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
  287. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
  288. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +1 -1
  289. claude_mpm/services/unified/deployment_strategies/local.py +1 -1
  290. claude_mpm/services/version_control/VERSION +1 -0
  291. claude_mpm/services/version_control/conflict_resolution.py +6 -4
  292. claude_mpm/services/version_service.py +104 -1
  293. claude_mpm/services/visualization/mermaid_generator.py +2 -3
  294. claude_mpm/skills/__init__.py +21 -0
  295. claude_mpm/skills/agent_skills_injector.py +324 -0
  296. claude_mpm/skills/bundled/.gitkeep +2 -0
  297. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  298. claude_mpm/skills/bundled/api-documentation.md +393 -0
  299. claude_mpm/skills/bundled/async-testing.md +571 -0
  300. claude_mpm/skills/bundled/code-review.md +143 -0
  301. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  302. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  303. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  304. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  305. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  306. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  307. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  308. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  309. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  310. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  311. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  312. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  313. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  314. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  315. claude_mpm/skills/bundled/database-migration.md +199 -0
  316. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  317. claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +63 -0
  318. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  319. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  320. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  321. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  322. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  323. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  324. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  325. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  326. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  327. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  328. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  329. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  330. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  331. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  332. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  333. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  334. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  335. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  336. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  337. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  338. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  339. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  340. claude_mpm/skills/bundled/git-workflow.md +414 -0
  341. claude_mpm/skills/bundled/imagemagick.md +204 -0
  342. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  343. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  344. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  345. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  346. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  347. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  348. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  349. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  350. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  351. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  352. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  353. claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +202 -0
  354. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  355. claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +54 -0
  356. claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +322 -0
  357. claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  358. claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +202 -0
  359. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  360. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  361. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  362. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  363. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  364. claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +202 -0
  365. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  366. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  367. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  368. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  369. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  370. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  371. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  372. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  373. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  374. claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +22 -0
  375. claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +2 -0
  376. claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +202 -0
  377. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  378. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  379. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  380. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  381. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  382. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  383. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  384. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  385. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  386. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  387. claude_mpm/skills/bundled/pdf.md +141 -0
  388. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  389. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  390. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  391. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  392. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  393. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  394. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  395. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  396. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  397. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  398. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  399. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  400. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  401. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  402. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  403. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  404. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  405. claude_mpm/skills/bundled/security-scanning.md +327 -0
  406. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  407. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  408. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  409. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  410. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  411. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  412. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  413. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  414. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  415. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  416. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  417. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  418. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  419. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  420. claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +158 -0
  421. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  422. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  423. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  424. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  425. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  426. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  427. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  428. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  429. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  430. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  431. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  432. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  433. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  434. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  435. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  436. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  437. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  438. claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +202 -0
  439. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  440. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  441. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  442. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  443. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  444. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  445. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  446. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  447. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  448. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  449. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  450. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  451. claude_mpm/skills/bundled/xlsx.md +157 -0
  452. claude_mpm/skills/registry.py +97 -9
  453. claude_mpm/skills/skills_registry.py +347 -0
  454. claude_mpm/skills/skills_service.py +739 -0
  455. claude_mpm/templates/questions/EXAMPLES.md +501 -0
  456. claude_mpm/templates/questions/__init__.py +43 -0
  457. claude_mpm/templates/questions/base.py +193 -0
  458. claude_mpm/templates/questions/pr_strategy.py +314 -0
  459. claude_mpm/templates/questions/project_init.py +388 -0
  460. claude_mpm/templates/questions/ticket_mgmt.py +397 -0
  461. claude_mpm/tools/README_SOCKETIO_DEBUG.md +224 -0
  462. claude_mpm/tools/__main__.py +8 -8
  463. claude_mpm/tools/code_tree_analyzer/README.md +64 -0
  464. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  465. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  466. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  467. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  468. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  469. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  470. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  471. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  472. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  473. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  474. claude_mpm/utils/agent_dependency_loader.py +5 -5
  475. claude_mpm/utils/dependency_cache.py +3 -1
  476. claude_mpm/utils/gitignore.py +241 -0
  477. claude_mpm/utils/log_cleanup.py +3 -3
  478. claude_mpm/utils/robust_installer.py +3 -5
  479. claude_mpm/utils/structured_questions.py +619 -0
  480. claude_mpm-4.25.10.dist-info/METADATA +789 -0
  481. {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/RECORD +485 -240
  482. claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
  483. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
  484. claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
  485. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
  486. claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
  487. claude_mpm/cli/commands/mpm_init.py +0 -2008
  488. claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
  489. claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
  490. claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
  491. claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
  492. claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
  493. claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
  494. claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
  495. claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
  496. claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
  497. claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
  498. claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
  499. claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
  500. claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
  501. claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
  502. claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
  503. claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
  504. claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
  505. claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
  506. claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
  507. claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
  508. claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
  509. claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
  510. claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
  511. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
  512. claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
  513. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
  514. claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
  515. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
  516. claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
  517. claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
  518. claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
  519. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
  520. claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
  521. claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
  522. claude_mpm/dashboard/static/dist/dashboard.js +0 -2
  523. claude_mpm/dashboard/static/dist/react/events.js +0 -30
  524. claude_mpm/dashboard/static/dist/socket-client.js +0 -2
  525. claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
  526. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  527. claude_mpm-4.16.0.dist-info/METADATA +0 -453
  528. {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/WHEEL +0 -0
  529. {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/entry_points.txt +0 -0
  530. {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/licenses/LICENSE +0 -0
  531. {claude_mpm-4.16.0.dist-info → claude_mpm-4.25.10.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-tree.js","sources":["../../js/components/code-tree.js"],"sourcesContent":["/**\n * Code Tree Component\n * \n * D3.js-based tree visualization for displaying AST-based code structure.\n * Shows modules, classes, functions, and methods with complexity-based coloring.\n * Provides real-time updates during code analysis.\n * \n * ===== CACHE CLEAR INSTRUCTIONS =====\n * If tree still moves/centers after update:\n * 1. Hard refresh: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)\n * 2. Or open DevTools (F12) → Network tab → Check \"Disable cache\" \n * 3. Or clear browser cache: Ctrl+Shift+Delete → Clear cached images and files\n * \n * Version: 2025-08-29T15:30:00Z - ALL CENTERING REMOVED\n * Last Update: Completely disabled tree centering/movement on node clicks\n * \n * REFACTORED: 2025-09-05 - Extracted utilities, constants, search, and breadcrumb modules\n */\n\n// Load dependencies - these should be loaded in the HTML before this file\n// Shared services\n// <script src=\"/static/js/shared/tooltip-service.js\"></script>\n// <script src=\"/static/js/shared/dom-helpers.js\"></script>\n// <script src=\"/static/js/shared/event-bus.js\"></script>\n// <script src=\"/static/js/shared/logger.js\"></script>\n// Tree modules\n// <script src=\"/static/js/components/code-tree/tree-utils.js\"></script>\n// <script src=\"/static/js/components/code-tree/tree-constants.js\"></script>\n// <script src=\"/static/js/components/code-tree/tree-search.js\"></script>\n// <script src=\"/static/js/components/code-tree/tree-breadcrumb.js\"></script>\n\nclass CodeTree {\n constructor() {\n // Initialize services\n this.tooltipService = window.tooltipService || null;\n this.domHelpers = window.domHelpers || null;\n this.eventBus = window.eventBus || null;\n this.logger = window.logger ? window.logger.createComponentLogger('CodeTree') : console;\n this.treeUtils = window.treeUtils || null;\n this.treeConstants = window.treeConstants || {};\n this.treeSearch = window.treeSearch || null;\n this.treeBreadcrumb = window.treeBreadcrumb || null;\n \n this.container = null;\n this.svg = null;\n this.treeData = null;\n this.root = null;\n this.treeLayout = null;\n this.treeGroup = null;\n this.nodes = new Map();\n this.stats = {\n files: 0,\n classes: 0,\n functions: 0,\n methods: 0,\n lines: 0\n };\n // Radial layout settings - use constants if available\n this.isRadialLayout = false; // Toggle for radial vs linear layout - defaulting to linear for better readability\n this.margin = this.treeConstants.DEFAULT_MARGIN || {top: 20, right: 20, bottom: 20, left: 20};\n this.width = (this.treeConstants.DEFAULT_WIDTH || 960) - this.margin.left - this.margin.right;\n this.height = (this.treeConstants.DEFAULT_HEIGHT || 600) - this.margin.top - this.margin.bottom;\n this.radius = Math.min(this.width, this.height) / 2;\n this.nodeId = 0;\n this.duration = this.treeConstants.ANIMATION_DURATION || 750;\n this.languageFilter = 'all';\n this.searchTerm = '';\n this.tooltip = null;\n this.initialized = false;\n this.analyzing = false;\n this.selectedNode = null;\n this.socket = null;\n this.autoDiscovered = false; // Track if auto-discovery has been done\n this.zoom = null; // Store zoom behavior\n\n // Structured data properties\n this.structuredDataContent = null;\n this.selectedASTItem = null;\n this.activeNode = null; // Track currently active node\n this.loadingNodes = new Set(); // Track nodes that are loading\n this.bulkLoadMode = false; // Track bulk loading preference\n this.expandedPaths = new Set(); // Track which paths are expanded\n this.focusedNode = null; // Track the currently focused directory\n this.horizontalNodes = new Set(); // Track nodes that should have horizontal text\n this.centralSpine = new Set(); // Track the main path through the tree\n \n // CRITICAL FIX: Bind methods to preserve 'this' context when called by D3 event handlers\n this.onNodeClick = this.onNodeClick.bind(this);\n this.showTooltip = this.showTooltip.bind(this);\n this.hideTooltip = this.hideTooltip.bind(this);\n }\n\n /**\n * Initialize the code tree visualization\n */\n initialize() {\n if (this.initialized) {\n return;\n }\n \n this.container = document.getElementById('code-tree-container');\n if (!this.container) {\n console.error('Code tree container not found');\n return;\n }\n \n // Check if tab is visible\n const tabPanel = document.getElementById('code-tab');\n if (!tabPanel) {\n console.error('Code tab panel not found');\n return;\n }\n \n // Check if working directory is set\n const workingDir = this.getWorkingDirectory();\n if (!workingDir || workingDir === 'Loading...' || workingDir === 'Not selected') {\n this.showNoWorkingDirectoryMessage();\n this.initialized = true;\n return;\n }\n \n // Initialize always\n this.setupControls();\n this.initializeTreeData();\n this.subscribeToEvents();\n this.initializeStructuredData();\n \n // Set initial status message\n const breadcrumbContent = document.getElementById('breadcrumb-content');\n if (breadcrumbContent && !this.analyzing) {\n this.updateActivityTicker('Loading project structure...', 'info');\n }\n \n // Only create visualization if tab is visible\n if (tabPanel.classList.contains('active')) {\n this.createVisualization();\n if (this.root && this.svg) {\n this.update(this.root);\n }\n // Auto-discover root level when tab is active\n this.autoDiscoverRootLevel();\n }\n \n this.initialized = true;\n }\n\n /**\n * Render visualization when tab becomes visible\n */\n renderWhenVisible() {\n // Check if working directory is set\n const workingDir = this.getWorkingDirectory();\n if (!workingDir || workingDir === 'Loading...' || workingDir === 'Not selected') {\n this.showNoWorkingDirectoryMessage();\n return;\n }\n \n // If no directory message is shown, remove it\n this.removeNoWorkingDirectoryMessage();\n \n if (!this.initialized) {\n this.initialize();\n return;\n }\n \n if (!this.svg) {\n this.createVisualization();\n if (this.svg && this.treeGroup) {\n this.update(this.root);\n }\n } else {\n // Force update with current data\n if (this.root && this.svg) {\n this.update(this.root);\n }\n }\n \n // Auto-discover root level if not done yet\n if (!this.autoDiscovered) {\n this.autoDiscoverRootLevel();\n }\n }\n\n /**\n * Set up control event handlers\n */\n setupControls() {\n // Remove analyze and cancel button handlers since they're no longer in the UI\n\n const languageFilter = document.getElementById('language-filter');\n if (languageFilter) {\n languageFilter.addEventListener('change', (e) => {\n this.languageFilter = e.target.value;\n this.filterTree();\n });\n }\n\n const searchBox = document.getElementById('code-search');\n if (searchBox) {\n searchBox.addEventListener('input', (e) => {\n this.searchTerm = e.target.value.toLowerCase();\n this.filterTree();\n });\n }\n\n // Note: Expand/collapse/reset buttons are now handled by the tree controls toolbar\n // which is created dynamically in addTreeControls()\n \n const toggleLegendBtn = document.getElementById('code-toggle-legend');\n if (toggleLegendBtn) {\n toggleLegendBtn.addEventListener('click', () => this.toggleLegend());\n }\n \n // Listen for working directory changes\n document.addEventListener('workingDirectoryChanged', (e) => {\n this.onWorkingDirectoryChanged(e.detail.directory);\n });\n }\n \n /**\n * Handle working directory change\n */\n onWorkingDirectoryChanged(newDirectory) {\n if (!newDirectory || newDirectory === 'Loading...' || newDirectory === 'Not selected') {\n // Show no directory message\n this.showNoWorkingDirectoryMessage();\n // Reset tree state\n this.autoDiscovered = false;\n this.analyzing = false;\n this.nodes.clear();\n this.loadingNodes.clear(); // Clear loading state tracking\n this.stats = {\n files: 0,\n classes: 0,\n functions: 0,\n methods: 0,\n lines: 0\n };\n this.updateStats();\n return;\n }\n \n // Remove any no directory message\n this.removeNoWorkingDirectoryMessage();\n \n // Reset discovery state for new directory\n this.autoDiscovered = false;\n this.analyzing = false;\n \n // Clear existing data\n this.nodes.clear();\n this.loadingNodes.clear(); // Clear loading state tracking\n this.stats = {\n files: 0,\n classes: 0,\n functions: 0,\n methods: 0,\n lines: 0\n };\n \n // Re-initialize with new directory\n this.initializeTreeData();\n if (this.svg) {\n this.update(this.root);\n }\n \n // Check if Code tab is currently active\n const tabPanel = document.getElementById('code-tab');\n if (tabPanel && tabPanel.classList.contains('active')) {\n // Auto-discover in the new directory\n this.autoDiscoverRootLevel();\n }\n \n this.updateStats();\n }\n\n /**\n * Show loading spinner\n */\n showLoading() {\n let loadingDiv = document.getElementById('code-tree-loading');\n if (!loadingDiv) {\n // Create loading element if it doesn't exist\n const container = document.getElementById('code-tree-container');\n if (container) {\n loadingDiv = document.createElement('div');\n loadingDiv.id = 'code-tree-loading';\n loadingDiv.innerHTML = `\n <div class=\"code-tree-spinner\"></div>\n <div class=\"code-tree-loading-text\">Analyzing code structure...</div>\n `;\n container.appendChild(loadingDiv);\n }\n }\n if (loadingDiv) {\n loadingDiv.classList.remove('hidden');\n }\n }\n\n /**\n * Hide loading spinner\n */\n hideLoading() {\n const loadingDiv = document.getElementById('code-tree-loading');\n if (loadingDiv) {\n loadingDiv.classList.add('hidden');\n }\n }\n\n /**\n * Create the D3.js visualization\n */\n createVisualization() {\n if (typeof d3 === 'undefined') {\n console.error('D3.js is not loaded');\n return;\n }\n\n const container = d3.select('#code-tree-container');\n container.selectAll('*').remove();\n \n // Add tree controls toolbar\n this.addTreeControls();\n\n // Breadcrumb navigation removed - redundant with root node display\n // this.addBreadcrumb();\n\n if (!container || !container.node()) {\n console.error('Code tree container not found');\n return;\n }\n\n // Calculate dimensions\n const containerNode = container.node();\n const containerWidth = containerNode.clientWidth || 960;\n const containerHeight = containerNode.clientHeight || 600;\n\n this.width = containerWidth - this.margin.left - this.margin.right;\n this.height = containerHeight - this.margin.top - this.margin.bottom;\n this.radius = Math.min(this.width, this.height) / 2;\n\n // Create SVG\n this.svg = container.append('svg')\n .attr('width', containerWidth)\n .attr('height', containerHeight);\n\n // Create tree group with appropriate centering\n const centerX = containerWidth / 2;\n const centerY = containerHeight / 2;\n \n // Different initial positioning for different layouts\n if (this.isRadialLayout) {\n // Radial: center in the middle of the canvas\n this.treeGroup = this.svg.append('g')\n .attr('transform', `translate(${centerX},${centerY})`);\n } else {\n // Linear: start from left with some margin\n this.treeGroup = this.svg.append('g')\n .attr('transform', `translate(${this.margin.left + 100},${centerY})`);\n }\n\n // Create tree layout with improved spacing\n if (this.isRadialLayout) {\n // Use d3.cluster for better radial distribution\n this.treeLayout = d3.cluster()\n .size([2 * Math.PI, this.radius - 100])\n .separation((a, b) => {\n // Enhanced separation for radial layout\n if (a.parent == b.parent) {\n // Base separation on tree depth for better spacing\n const depthFactor = Math.max(1, 4 - a.depth);\n // Increase spacing for nodes with many siblings\n const siblingCount = a.parent ? (a.parent.children?.length || 1) : 1;\n const siblingFactor = siblingCount > 5 ? 2 : (siblingCount > 3 ? 1.5 : 1);\n // More spacing at outer levels where circumference is larger\n const radiusFactor = 1 + (a.depth * 0.2);\n return (depthFactor * siblingFactor) / (a.depth || 1) * radiusFactor;\n } else {\n // Different parents - ensure enough space\n return 4 / (a.depth || 1);\n }\n });\n } else {\n // Linear layout with dynamic sizing based on node count\n // Use nodeSize for consistent spacing regardless of tree size\n this.treeLayout = d3.tree()\n .nodeSize([30, 200]) // Fixed spacing: 30px vertical, 200px horizontal\n .separation((a, b) => {\n // Consistent separation for linear layout\n if (a.parent == b.parent) {\n // Same parent - standard spacing\n return 1;\n } else {\n // Different parents - slightly more space\n return 1.5;\n }\n });\n }\n\n // Enable zoom and pan functionality for better navigation\n this.zoom = d3.zoom()\n .scaleExtent([0.1, 3]) // Allow zoom from 10% to 300%\n .on('zoom', (event) => {\n // Apply zoom transform to the tree group\n this.treeGroup.attr('transform', event.transform);\n\n // Keep text size constant by applying inverse scaling\n this.adjustTextSizeForZoom(event.transform.k);\n\n // Update zoom level display\n this.updateZoomLevel(event.transform.k);\n });\n\n // Apply zoom behavior to SVG\n this.svg.call(this.zoom);\n\n // Add keyboard shortcuts for zoom\n this.addZoomKeyboardShortcuts();\n\n console.log('[CodeTree] Zoom and pan functionality enabled');\n\n // Add controls overlay\n this.addVisualizationControls();\n\n // Create tooltip\n this.tooltip = d3.select('body').append('div')\n .attr('class', 'code-tree-tooltip')\n .style('opacity', 0)\n .style('position', 'absolute')\n .style('background', 'rgba(0, 0, 0, 0.8)')\n .style('color', 'white')\n .style('padding', '8px')\n .style('border-radius', '4px')\n .style('font-size', '12px')\n .style('pointer-events', 'none');\n }\n\n /**\n * Clear all D3 visualization elements\n */\n clearD3Visualization() {\n if (this.treeGroup) {\n // Remove all existing nodes and links\n this.treeGroup.selectAll('g.node').remove();\n this.treeGroup.selectAll('path.link').remove();\n }\n // Reset node ID counter for proper tracking\n this.nodeId = 0;\n }\n \n /**\n * Initialize tree data structure\n */\n initializeTreeData() {\n const workingDir = this.getWorkingDirectory();\n // Use a more descriptive root name that doesn't look like a clickable button\n const dirName = 'Project Root'; // Always use generic name for root\n\n // Use absolute path for consistency with API expectations\n this.treeData = {\n name: dirName,\n path: workingDir || '.', // Use working directory or fallback to '.'\n type: 'root',\n isDirectory: true, // Critical: Mark root as directory for proper handling\n children: [],\n loaded: false,\n expanded: true, // Start expanded\n hasChildren: true, // Root always has potential children\n isRoot: true // Mark as root node for special handling\n };\n\n if (typeof d3 !== 'undefined') {\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n }\n }\n\n /**\n * Subscribe to code analysis events\n */\n subscribeToEvents() {\n if (!this.socket) {\n // CRITICAL FIX: Create our own socket connection if no shared socket exists\n // This ensures the tree view has a working WebSocket connection\n if (window.socket && window.socket.connected) {\n console.log('[CodeTree] Using existing global socket');\n this.socket = window.socket;\n this.setupEventHandlers();\n } else if (window.dashboard?.socketClient?.socket && window.dashboard.socketClient.socket.connected) {\n console.log('[CodeTree] Using dashboard socket');\n this.socket = window.dashboard.socketClient.socket;\n this.setupEventHandlers();\n } else if (window.socketClient?.socket && window.socketClient.socket.connected) {\n console.log('[CodeTree] Using socketClient socket');\n this.socket = window.socketClient.socket;\n this.setupEventHandlers();\n } else if (window.io) {\n // Create our own socket connection like the simple view does\n console.log('[CodeTree] Creating new socket connection');\n try {\n this.socket = io('/');\n \n this.socket.on('connect', () => {\n console.log('[CodeTree] Socket connected successfully');\n this.setupEventHandlers();\n });\n \n this.socket.on('disconnect', () => {\n console.log('[CodeTree] Socket disconnected');\n });\n \n this.socket.on('connect_error', (error) => {\n console.error('[CodeTree] Socket connection error:', error);\n });\n } catch (error) {\n console.error('[CodeTree] Failed to create socket connection:', error);\n }\n } else {\n console.error('[CodeTree] Socket.IO not available - cannot subscribe to events');\n }\n }\n }\n\n /**\n * Automatically discover root-level objects when tab opens\n */\n autoDiscoverRootLevel() {\n if (this.autoDiscovered || this.analyzing) {\n return;\n }\n \n // Update activity ticker\n this.updateActivityTicker('🔍 Discovering project structure...', 'info');\n \n // Get working directory\n const workingDir = this.getWorkingDirectory();\n if (!workingDir || workingDir === 'Loading...' || workingDir === 'Not selected') {\n console.warn('Cannot auto-discover: no working directory set');\n this.showNoWorkingDirectoryMessage();\n return;\n }\n \n // Ensure we have an absolute path\n if (!workingDir.startsWith('/') && !workingDir.match(/^[A-Z]:\\\\/)) {\n console.error('Working directory is not absolute:', workingDir);\n this.showNotification('Invalid working directory path', 'error');\n return;\n }\n \n this.autoDiscovered = true;\n this.analyzing = true;\n \n // Clear any existing nodes\n this.nodes.clear();\n this.loadingNodes.clear(); // Clear loading state for fresh discovery\n this.stats = {\n files: 0,\n classes: 0,\n functions: 0,\n methods: 0,\n lines: 0\n };\n \n // Subscribe to events if not already done (for other features)\n if (this.socket && !this.socket.hasListeners('code:node:found')) {\n this.setupEventHandlers();\n }\n \n // Update UI\n this.showLoading();\n const dirName = workingDir.split('/').pop() || 'Project Root';\n this.updateBreadcrumb(`Discovering structure in ${dirName}...`, 'info');\n \n // Use REST API for initial discovery (more reliable than WebSocket)\n console.log(`🚀 [ROOT DISCOVERY] Using REST API for root: ${workingDir}`);\n \n const apiUrl = `${window.location.origin}/api/directory?path=${encodeURIComponent(workingDir)}`;\n \n fetch(apiUrl)\n .then(response => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n return response.json();\n })\n .then(data => {\n console.log('✅ [ROOT DISCOVERY] REST API response:', data);\n \n // Process the response\n if (data.contents && Array.isArray(data.contents)) {\n // Update root node with children\n this.treeData.children = data.contents.map(item => ({\n name: item.name,\n path: item.path,\n type: item.type || (item.is_directory ? 'directory' : 'file'),\n size: item.size,\n hasChildren: item.is_directory,\n children: [],\n loaded: false\n }));\n \n this.treeData.loaded = true;\n \n // Update D3 hierarchy\n if (typeof d3 !== 'undefined') {\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n // Expand root node to show children\n if (this.root.children) {\n this.root.children.forEach(child => {\n child._children = null;\n });\n }\n }\n \n // Update the visualization\n if (this.svg) {\n this.update(this.root);\n }\n \n // Update stats\n const fileCount = data.contents.filter(item => !item.is_directory).length;\n const dirCount = data.contents.filter(item => item.is_directory).length;\n \n this.stats.files = fileCount;\n this.updateStats();\n \n this.updateBreadcrumb(\n `📁 Found ${dirCount} directories and ${fileCount} files`,\n 'success'\n );\n \n this.updateActivityTicker(\n `📁 Found ${dirCount} directories and ${fileCount} files`,\n 'success'\n );\n \n // Add to events display\n this.addEventToDisplay(\n `📁 Loaded ${data.contents.length} items from project root`,\n 'info'\n );\n }\n \n this.analyzing = false;\n this.hideLoading();\n })\n .catch(error => {\n console.error('[ROOT DISCOVERY] Error:', error);\n this.analyzing = false;\n this.hideLoading();\n this.showNotification(`Failed to load directory: ${error.message}`, 'error');\n \n // Try WebSocket as fallback\n if (this.socket) {\n console.log('[ROOT DISCOVERY] Falling back to WebSocket');\n const requestPayload = {\n path: workingDir,\n depth: 'top_level',\n languages: this.getSelectedLanguages(),\n ignore_patterns: document.getElementById('ignore-patterns')?.value || '',\n request_id: `discover_${Date.now()}`\n };\n this.socket.emit('code:discover:top_level', requestPayload);\n }\n });\n \n // Update stats display\n this.updateStats();\n }\n \n /**\n * Legacy analyzeCode method - redirects to auto-discovery\n */\n analyzeCode() {\n if (this.analyzing) {\n return;\n }\n\n // Redirect to auto-discovery\n this.autoDiscoverRootLevel();\n }\n\n /**\n * Cancel ongoing analysis - removed since we no longer have a cancel button\n */\n cancelAnalysis() {\n this.analyzing = false;\n this.hideLoading();\n this.loadingNodes.clear(); // Clear loading state on cancellation\n\n if (this.socket) {\n this.socket.emit('code:analysis:cancel');\n }\n }\n\n /**\n * Add tree control toolbar with expand/collapse and other controls\n */\n addTreeControls() {\n const container = d3.select('#code-tree-container');\n \n // Remove any existing controls\n container.select('.tree-controls-toolbar').remove();\n \n const toolbar = container.append('div')\n .attr('class', 'tree-controls-toolbar');\n \n // Expand All button\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Expand all loaded directories')\n .text('⊞')\n .on('click', () => this.expandAll());\n \n // Collapse All button \n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Collapse all directories')\n .text('⊟')\n .on('click', () => this.collapseAll());\n \n // Bulk Load Toggle\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('id', 'bulk-load-toggle')\n .attr('title', 'Toggle bulk loading (load 2 levels at once)')\n .text('↕')\n .on('click', () => this.toggleBulkLoad());\n \n // Layout Toggle\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Toggle between radial and linear layouts')\n .text('◎')\n .on('click', () => this.toggleLayout());\n\n // Zoom In\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Zoom in')\n .text('🔍+')\n .on('click', () => this.zoomIn());\n\n // Zoom Out\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Zoom out')\n .text('🔍-')\n .on('click', () => this.zoomOut());\n\n // Reset Zoom\n toolbar.append('button')\n .attr('class', 'tree-control-btn')\n .attr('title', 'Reset zoom to fit tree')\n .text('⌂')\n .on('click', () => this.resetZoom());\n\n // Zoom Level Display\n toolbar.append('span')\n .attr('class', 'zoom-level-display')\n .attr('id', 'zoom-level-display')\n .text('100%')\n .style('margin-left', '8px')\n .style('font-size', '11px')\n .style('color', '#718096');\n\n // Path Search\n const searchInput = toolbar.append('input')\n .attr('class', 'tree-control-btn')\n .attr('type', 'text')\n .attr('placeholder', 'Search...')\n .attr('title', 'Search for files and directories')\n .style('width', '120px')\n .style('text-align', 'left')\n .on('input', (event) => this.searchTree(event.target.value))\n .on('keydown', (event) => {\n if (event.key === 'Escape') {\n event.target.value = '';\n this.searchTree('');\n }\n });\n }\n\n /**\n * Add breadcrumb navigation\n */\n addBreadcrumb() {\n const container = d3.select('#code-tree-container');\n \n // Remove any existing breadcrumb\n container.select('.tree-breadcrumb').remove();\n \n const breadcrumb = container.append('div')\n .attr('class', 'tree-breadcrumb');\n \n const pathDiv = breadcrumb.append('div')\n .attr('class', 'breadcrumb-path')\n .attr('id', 'tree-breadcrumb-path');\n \n // Initialize with working directory\n this.updateBreadcrumbPath('/');\n }\n\n /**\n * Update breadcrumb path based on current navigation\n */\n updateBreadcrumbPath(currentPath) {\n const pathDiv = d3.select('#tree-breadcrumb-path');\n pathDiv.selectAll('*').remove();\n \n const workingDir = this.getWorkingDirectory();\n if (!workingDir || workingDir === 'Loading...' || workingDir === 'Not selected') {\n pathDiv.text('No project selected');\n return;\n }\n \n // Build path segments\n const segments = currentPath === '/' ? \n [workingDir.split('/').pop() || 'Root'] :\n currentPath.split('/').filter(s => s.length > 0);\n \n segments.forEach((segment, index) => {\n if (index > 0) {\n pathDiv.append('span')\n .attr('class', 'breadcrumb-separator')\n .text('/');\n }\n \n pathDiv.append('span')\n .attr('class', index === segments.length - 1 ? 'breadcrumb-segment current' : 'breadcrumb-segment')\n .text(segment)\n .on('click', () => {\n if (index < segments.length - 1) {\n // Navigate to parent path\n const parentPath = segments.slice(0, index + 1).join('/');\n this.navigateToPath(parentPath);\n }\n });\n });\n }\n\n /**\n * Expand all currently loaded directories\n */\n expandAll() {\n if (!this.root) return;\n \n const expandNode = (node) => {\n if ((node.data.type === 'directory' || node.data.type === 'root' || node.data.isDirectory) && node.data.loaded === true) {\n if (node._children) {\n node.children = node._children;\n node._children = null;\n node.data.expanded = true;\n }\n }\n if (node.children) {\n node.children.forEach(expandNode);\n }\n };\n \n expandNode(this.root);\n this.update(this.root);\n this.showNotification('Expanded all loaded directories', 'success');\n }\n\n /**\n * Collapse all directories to root level\n */\n collapseAll() {\n if (!this.root) return;\n \n const collapseNode = (node) => {\n if ((node.data.type === 'directory' || node.data.type === 'root' || node.data.isDirectory) && node.children) {\n node._children = node.children;\n node.children = null;\n node.data.expanded = false;\n }\n if (node._children) {\n node._children.forEach(collapseNode);\n }\n };\n \n collapseNode(this.root);\n this.update(this.root);\n this.showNotification('Collapsed all directories', 'info');\n }\n\n /**\n * Toggle bulk loading mode\n */\n toggleBulkLoad() {\n this.bulkLoadMode = !this.bulkLoadMode;\n const button = d3.select('#bulk-load-toggle');\n \n if (this.bulkLoadMode) {\n button.classed('active', true);\n this.showNotification('Bulk load enabled - will load 2 levels deep', 'info');\n } else {\n button.classed('active', false);\n this.showNotification('Bulk load disabled - load 1 level at a time', 'info');\n }\n }\n\n /**\n * Navigate to a specific path in the tree\n */\n navigateToPath(path) {\n // Implementation for navigating to a specific path\n // This would expand the tree to show the specified path\n // this.updateBreadcrumbPath(path); // Breadcrumb removed\n this.showNotification(`Navigating to: ${path}`, 'info');\n }\n\n /**\n * Search the tree for matching files/directories\n */\n searchTree(query) {\n if (!this.root || !this.treeGroup) return;\n \n const searchTerm = query.toLowerCase().trim();\n \n // Clear previous search highlights\n this.treeGroup.selectAll('.code-node')\n .classed('search-match', false);\n \n if (!searchTerm) {\n return; // No search term, just clear highlights\n }\n \n // Find matching nodes\n const matchingNodes = [];\n const searchNode = (node) => {\n const name = (node.data.name || '').toLowerCase();\n const path = (node.data.path || '').toLowerCase();\n \n if (name.includes(searchTerm) || path.includes(searchTerm)) {\n matchingNodes.push(node);\n }\n \n if (node.children) {\n node.children.forEach(searchNode);\n }\n if (node._children) {\n node._children.forEach(searchNode);\n }\n };\n \n searchNode(this.root);\n \n // Highlight matching nodes\n if (matchingNodes.length > 0) {\n // Get all current nodes in the tree\n const allNodes = this.treeGroup.selectAll('.code-node').data();\n \n matchingNodes.forEach(matchNode => {\n // Find the corresponding DOM node\n const domNode = this.treeGroup.selectAll('.code-node')\n .filter(d => d.data.path === matchNode.data.path);\n domNode.classed('search-match', true);\n \n // Expand parent path to show the match\n this.expandPathToNode(matchNode);\n });\n \n this.showNotification(`Found ${matchingNodes.length} matches`, 'success');\n \n // Auto-center on first match if in radial layout - REMOVED\n // Centering functionality has been disabled to prevent unwanted repositioning\n // if (matchingNodes.length > 0 && this.isRadialLayout) {\n // this.centerOnNode ? this.centerOnNode(matchingNodes[0]) : this.centerOnNodeRadial(matchingNodes[0]);\n // }\n } else {\n this.showNotification('No matches found', 'info');\n }\n }\n\n /**\n * Expand the tree path to show a specific node\n */\n expandPathToNode(targetNode) {\n const pathToExpand = [];\n let current = targetNode.parent;\n \n // Build path from node to root\n while (current && current !== this.root) {\n pathToExpand.unshift(current);\n current = current.parent;\n }\n \n // Expand each node in the path\n pathToExpand.forEach(node => {\n if (node.data.type === 'directory' && node._children) {\n node.children = node._children;\n node._children = null;\n node.data.expanded = true;\n }\n });\n \n // Update the visualization if we expanded anything\n if (pathToExpand.length > 0) {\n this.update(this.root);\n }\n }\n\n /**\n * Create the events display area\n */\n createEventsDisplay() {\n let eventsContainer = document.getElementById('analysis-events');\n if (!eventsContainer) {\n const treeContainer = document.getElementById('code-tree-container');\n if (treeContainer) {\n eventsContainer = document.createElement('div');\n eventsContainer.id = 'analysis-events';\n eventsContainer.className = 'analysis-events';\n eventsContainer.style.display = 'none';\n treeContainer.appendChild(eventsContainer);\n }\n }\n }\n\n /**\n * Clear the events display\n */\n clearEventsDisplay() {\n const eventsContainer = document.getElementById('analysis-events');\n if (eventsContainer) {\n eventsContainer.innerHTML = '';\n eventsContainer.style.display = 'block';\n }\n }\n\n /**\n * Add an event to the display\n */\n addEventToDisplay(message, type = 'info') {\n const eventsContainer = document.getElementById('analysis-events');\n if (eventsContainer) {\n const eventEl = document.createElement('div');\n eventEl.className = 'analysis-event';\n eventEl.style.borderLeftColor = type === 'warning' ? '#f59e0b' : \n type === 'error' ? '#ef4444' : '#3b82f6';\n \n const timestamp = new Date().toLocaleTimeString();\n eventEl.innerHTML = `<span style=\"color: #718096;\">[${timestamp}]</span> ${message}`;\n \n eventsContainer.appendChild(eventEl);\n // Auto-scroll to bottom\n eventsContainer.scrollTop = eventsContainer.scrollHeight;\n }\n }\n\n /**\n * Setup Socket.IO event handlers\n */\n setupEventHandlers() {\n if (!this.socket) return;\n\n // Analysis lifecycle events\n this.socket.on('code:analysis:accepted', (data) => this.onAnalysisAccepted(data));\n this.socket.on('code:analysis:queued', (data) => this.onAnalysisQueued(data));\n this.socket.on('code:analysis:start', (data) => this.onAnalysisStart(data));\n this.socket.on('code:analysis:complete', (data) => this.onAnalysisComplete(data));\n this.socket.on('code:analysis:cancelled', (data) => this.onAnalysisCancelled(data));\n this.socket.on('code:analysis:error', (data) => this.onAnalysisError(data));\n\n // Node discovery events\n this.socket.on('code:top_level:discovered', (data) => this.onTopLevelDiscovered(data));\n this.socket.on('code:directory:discovered', (data) => this.onDirectoryDiscovered(data));\n this.socket.on('code:file:discovered', (data) => this.onFileDiscovered(data));\n this.socket.on('code:file:analyzed', (data) => {\n console.log('📨 [SOCKET] Received code:file:analyzed event');\n this.onFileAnalyzed(data);\n });\n this.socket.on('code:node:found', (data) => this.onNodeFound(data));\n\n // Progress updates\n this.socket.on('code:analysis:progress', (data) => this.onProgressUpdate(data));\n\n // Error handling\n this.socket.on('code:analysis:error', (data) => {\n console.error('❌ [FILE ANALYSIS] Analysis error:', data);\n this.showNotification(`Analysis error: ${data.error || 'Unknown error'}`, 'error');\n });\n\n // Generic error handling\n this.socket.on('error', (error) => {\n console.error('❌ [SOCKET] Socket error:', error);\n });\n\n // Socket connection status\n this.socket.on('connect', () => {\n console.log('✅ [SOCKET] Connected to server, analysis service should be available');\n this.connectionStable = true;\n });\n\n this.socket.on('disconnect', () => {\n console.log('❌ [SOCKET] Disconnected from server - disabling AST analysis');\n this.connectionStable = false;\n // Clear any pending analysis timeouts\n if (this.analysisTimeouts) {\n this.analysisTimeouts.forEach((timeout, path) => {\n clearTimeout(timeout);\n this.loadingNodes.delete(path);\n });\n this.analysisTimeouts.clear();\n }\n });\n \n // Lazy loading responses\n this.socket.on('code:directory:contents', (data) => {\n // Update the requested directory with its contents\n if (data.path) {\n // Convert absolute path back to relative path to match tree nodes\n let searchPath = data.path;\n const workingDir = this.getWorkingDirectory();\n if (workingDir && searchPath.startsWith(workingDir)) {\n // Remove working directory prefix to get relative path\n searchPath = searchPath.substring(workingDir.length).replace(/^\\//, '');\n // If empty after removing prefix, it's the root\n if (!searchPath) {\n searchPath = '.';\n }\n }\n \n const node = this.findNodeByPath(searchPath);\n if (node && data.children) {\n // Find D3 node and remove loading pulse (use searchPath, not data.path)\n const d3Node = this.findD3NodeByPath(searchPath);\n if (d3Node && this.loadingNodes.has(searchPath)) {\n this.removeLoadingPulse(d3Node);\n this.loadingNodes.delete(searchPath); // Remove from loading set\n console.log('🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set:', searchPath);\n }\n node.children = data.children.map(child => {\n // Construct full path for child by combining parent path with child name\n // The backend now returns just the item name, not the full path\n let childPath;\n if (searchPath === '.' || searchPath === '') {\n // Root level - child path is just the name\n childPath = child.name || child.path;\n } else {\n // Subdirectory - combine parent path with child name\n // Use child.name (backend returns just the name) or fallback to child.path\n const childName = child.name || child.path;\n childPath = `${searchPath}/${childName}`;\n }\n \n return {\n ...child,\n path: childPath, // Override with constructed path\n loaded: child.type === 'directory' ? false : undefined,\n analyzed: child.type === 'file' ? false : undefined,\n expanded: false,\n children: []\n };\n });\n node.loaded = true;\n node.expanded = true; // Mark as expanded to show children\n \n // Update D3 hierarchy and make sure the node is expanded\n if (this.root && this.svg) {\n // Store old root to preserve expansion state\n const oldRoot = this.root;\n \n // Recreate hierarchy with updated data\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n // Preserve expansion state from old tree\n this.preserveExpansionState(oldRoot, this.root);\n \n // Find the D3 node again after hierarchy recreation\n const updatedD3Node = this.findD3NodeByPath(searchPath);\n if (updatedD3Node) {\n // D3.hierarchy already creates the children - just ensure visible\n if (updatedD3Node.children && updatedD3Node.children.length > 0) {\n updatedD3Node._children = null;\n updatedD3Node.data.expanded = true;\n console.log('✅ [D3 UPDATE] Node expanded after loading:', searchPath);\n }\n }\n \n // Update with the specific node for smooth animation\n this.update(updatedD3Node || this.root);\n }\n \n // Update stats based on discovered contents\n if (data.stats) {\n this.stats.files += data.stats.files || 0;\n this.stats.directories += data.stats.directories || 0;\n this.updateStats();\n }\n \n this.updateBreadcrumb(`Loaded ${data.path}`, 'success');\n this.hideLoading();\n }\n }\n });\n \n // Top level discovery response\n this.socket.on('code:top_level:discovered', (data) => {\n if (data.items && Array.isArray(data.items)) {\n \n // Add discovered items to the root node\n this.treeData.children = data.items.map(item => ({\n name: item.name,\n path: item.path,\n type: item.type,\n language: item.type === 'file' ? this.detectLanguage(item.path) : undefined,\n size: item.size,\n lines: item.lines,\n loaded: item.type === 'directory' ? false : undefined,\n analyzed: item.type === 'file' ? false : undefined,\n expanded: false,\n children: []\n }));\n \n this.treeData.loaded = true;\n \n // Update stats\n if (data.stats) {\n this.stats = { ...this.stats, ...data.stats };\n this.updateStats();\n }\n \n // Update D3 hierarchy\n if (typeof d3 !== 'undefined') {\n // Clear any existing nodes before creating new ones\n this.clearD3Visualization();\n \n // Create new hierarchy\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n if (this.svg) {\n this.update(this.root);\n }\n }\n \n this.analyzing = false;\n this.hideLoading();\n this.updateBreadcrumb(`Discovered ${data.items.length} root items`, 'success');\n this.showNotification(`Found ${data.items.length} items in project root`, 'success');\n }\n });\n }\n\n /**\n * Handle analysis start event\n */\n onAnalysisStart(data) {\n this.analyzing = true;\n const message = data.message || 'Starting code analysis...';\n \n // Update activity ticker\n this.updateActivityTicker('🚀 Starting analysis...', 'info');\n \n this.updateBreadcrumb(message, 'info');\n this.addEventToDisplay(`🚀 ${message}`, 'info');\n \n // Initialize or clear the tree\n if (!this.treeData || this.treeData.children.length === 0) {\n this.initializeTreeData();\n }\n \n // Reset stats\n this.stats = { \n files: 0, \n classes: 0, \n functions: 0, \n methods: 0, \n lines: 0 \n };\n this.updateStats();\n }\n\n /**\n * Handle top-level discovery event (initial root directory scan)\n */\n onTopLevelDiscovered(data) {\n // Received top-level discovery response\n \n // Update activity ticker\n this.updateActivityTicker(`📁 Discovered ${(data.items || []).length} top-level items`, 'success');\n \n // Add to events display\n this.addEventToDisplay(`📁 Found ${(data.items || []).length} top-level items in project root`, 'info');\n \n // The root node should receive the children\n const workingDir = this.getWorkingDirectory();\n const rootNode = this.findNodeByPath(workingDir);\n\n console.log(`🔎 Looking for root node with path \"${workingDir}\", found:`, rootNode ? {\n name: rootNode.name,\n path: rootNode.path,\n currentChildren: rootNode.children ? rootNode.children.length : 0\n } : 'NOT FOUND');\n \n if (rootNode && data.items) {\n console.log('🌳 Populating root node with children');\n \n // Update the root node with discovered children\n rootNode.children = data.items.map(child => {\n // CRITICAL FIX: Use consistent path format that matches API expectations\n // The API expects absolute paths, so construct them properly\n const workingDir = this.getWorkingDirectory();\n const childPath = workingDir ? `${workingDir}/${child.name}`.replace(/\\/+/g, '/') : child.name;\n\n console.log(` Adding child: ${child.name} with path: ${childPath}`);\n\n return {\n name: child.name,\n path: childPath, // Use absolute path for consistency\n type: child.type,\n loaded: child.type === 'directory' ? false : undefined, // Explicitly false for directories\n analyzed: child.type === 'file' ? false : undefined,\n expanded: false,\n children: child.type === 'directory' ? [] : undefined,\n size: child.size,\n has_code: child.has_code\n };\n });\n \n rootNode.loaded = true;\n rootNode.expanded = true;\n \n // Update D3 hierarchy and render\n if (this.root && this.svg) {\n // CRITICAL FIX: Preserve existing D3 node structure when possible\n // Instead of recreating the entire hierarchy, update the existing root\n if (this.root.data === this.treeData) {\n // Same root data object - update children in place\n console.log('📊 Updating existing D3 tree structure');\n \n // Create D3 hierarchy nodes for the new children\n this.root.children = rootNode.children.map(childData => {\n const childNode = d3.hierarchy(childData);\n childNode.parent = this.root;\n childNode.depth = 1;\n return childNode;\n });\n \n // Ensure root is marked as expanded\n this.root._children = null;\n this.root.data.expanded = true;\n } else {\n // Different root - need to recreate\n console.log('🔄 Recreating D3 tree structure');\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n }\n \n // Update the tree visualization\n this.update(this.root);\n }\n \n // Hide loading and show success\n this.hideLoading();\n this.updateBreadcrumb(`Discovered ${data.items.length} items`, 'success');\n this.showNotification(`Found ${data.items.length} top-level items`, 'success');\n } else {\n console.error('❌ Could not find root node to populate');\n this.showNotification('Failed to populate root directory', 'error');\n }\n \n // Mark analysis as complete\n this.analyzing = false;\n }\n \n /**\n * Handle directory discovered event\n */\n onDirectoryDiscovered(data) {\n // CRITICAL DEBUG: Log raw data received\n console.log('🔴 [RAW DATA] Exact data received from backend:', data);\n console.log('🔴 [RAW DATA] Data type:', typeof data);\n console.log('🔴 [RAW DATA] Data keys:', Object.keys(data));\n console.log('🔴 [RAW DATA] Children field:', data.children);\n console.log('🔴 [RAW DATA] Children type:', typeof data.children);\n console.log('🔴 [RAW DATA] Is children array?:', Array.isArray(data.children));\n console.log('🔴 [RAW DATA] Children length:', data.children ? data.children.length : 'undefined');\n \n // Update activity ticker first\n this.updateActivityTicker(`📁 Discovered: ${data.name || 'directory'}`);\n \n // Add to events display\n this.addEventToDisplay(`📁 Found ${(data.children || []).length} items in: ${data.name || data.path}`, 'info');\n \n console.log('✅ [SUBDIRECTORY LOADING] Received directory discovery response:', {\n path: data.path,\n name: data.name,\n childrenCount: (data.children || []).length,\n children: (data.children || []).map(c => ({ name: c.name, type: c.type })),\n workingDir: this.getWorkingDirectory(),\n fullEventData: data\n });\n \n // Convert absolute path back to relative path to match tree nodes\n let searchPath = data.path;\n const workingDir = this.getWorkingDirectory();\n if (workingDir && searchPath.startsWith(workingDir)) {\n // Remove working directory prefix to get relative path\n searchPath = searchPath.substring(workingDir.length).replace(/^\\//, '');\n // If empty after removing prefix, it's the root\n if (!searchPath) {\n searchPath = '.';\n }\n }\n \n console.log('🔎 Searching for node with path:', searchPath);\n \n // Find the node that was clicked to trigger this discovery\n const node = this.findNodeByPath(searchPath);\n \n console.log('🔍 Node search result:', {\n searchPath: searchPath,\n nodeFound: !!node,\n nodeName: node?.name,\n nodePath: node?.path,\n nodeChildren: node?.children?.length,\n dataHasChildren: !!data.children,\n dataChildrenLength: data.children?.length\n });\n \n // Debug: log all paths in the tree if node not found\n if (!node) {\n console.warn('Node not found! Logging all paths in tree:');\n this.logAllPaths(this.treeData);\n }\n \n // Located target node for expansion\n \n // Handle both cases: when children exist and when directory is empty\n if (node) {\n console.log('📦 Node found, checking children:', {\n nodeFound: true,\n dataHasChildren: 'children' in data,\n dataChildrenIsArray: Array.isArray(data.children),\n dataChildrenLength: data.children?.length,\n dataChildrenValue: data.children\n });\n \n if (data.children) {\n console.log(`📂 Updating node ${node.name} with ${data.children.length} children`);\n // Update the node with discovered children\n node.children = data.children.map(child => {\n // Construct full path for child by combining parent path with child name\n // The backend now returns just the item name, not the full path\n let childPath;\n if (searchPath === '.' || searchPath === '') {\n // Root level - child path is just the name\n childPath = child.name || child.path;\n } else {\n // Subdirectory - combine parent path with child name\n // Use child.name (backend returns just the name) or fallback to child.path\n const childName = child.name || child.path;\n childPath = `${searchPath}/${childName}`;\n }\n \n return {\n name: child.name,\n path: childPath, // Use constructed path instead of child.path\n type: child.type,\n loaded: child.type === 'directory' ? false : undefined,\n analyzed: child.type === 'file' ? false : undefined,\n expanded: false,\n children: child.type === 'directory' ? [] : undefined,\n size: child.size,\n has_code: child.has_code\n };\n });\n node.loaded = true;\n node.expanded = true;\n \n // Find D3 node and remove loading pulse (use searchPath, not data.path)\n const d3Node = this.findD3NodeByPath(searchPath);\n if (d3Node) {\n // Remove loading animation\n if (this.loadingNodes.has(searchPath)) {\n this.removeLoadingPulse(d3Node);\n this.loadingNodes.delete(searchPath); // Remove from loading set\n console.log('🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set (hierarchy update):', searchPath);\n }\n }\n \n // Update D3 hierarchy and redraw with expanded node\n if (this.root && this.svg) {\n // Store old root to preserve expansion state\n const oldRoot = this.root;\n \n // Recreate hierarchy with updated data\n this.root = d3.hierarchy(this.treeData);\n \n // Restore positions for smooth animation\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n // Preserve expansion state from old tree\n this.preserveExpansionState(oldRoot, this.root);\n \n // Find the D3 node again after hierarchy recreation\n const updatedD3Node = this.findD3NodeByPath(searchPath);\n if (updatedD3Node) {\n // CRITICAL FIX: D3.hierarchy() creates nodes with children already set\n // We just need to ensure they're not hidden in _children\n // When d3.hierarchy creates the tree, it puts all children in the 'children' array\n \n // If the node has children from d3.hierarchy, make sure they're visible\n if (updatedD3Node.children && updatedD3Node.children.length > 0) {\n // Children are already there from d3.hierarchy - just ensure not hidden\n updatedD3Node._children = null;\n updatedD3Node.data.expanded = true;\n \n console.log('✅ [D3 UPDATE] Node expanded with children:', {\n path: searchPath,\n d3ChildrenCount: updatedD3Node.children.length,\n dataChildrenCount: updatedD3Node.data.children ? updatedD3Node.data.children.length : 0,\n childPaths: updatedD3Node.children.map(c => c.data.path)\n });\n } else if (!updatedD3Node.children && updatedD3Node.data.children && updatedD3Node.data.children.length > 0) {\n // This shouldn't happen if d3.hierarchy is working correctly\n console.error('⚠️ [D3 UPDATE] Data has children but D3 node does not!', {\n path: searchPath,\n dataChildren: updatedD3Node.data.children\n });\n }\n }\n \n // Force update with the source node for smooth animation\n this.update(updatedD3Node || this.root);\n }\n \n // Provide better feedback for empty vs populated directories\n if (node.children.length === 0) {\n this.updateBreadcrumb(`Empty directory: ${node.name}`, 'info');\n this.showNotification(`Directory \"${node.name}\" is empty`, 'info');\n } else {\n this.updateBreadcrumb(`Loaded ${node.children.length} items from ${node.name}`, 'success');\n this.showNotification(`Loaded ${node.children.length} items from \"${node.name}\"`, 'success');\n }\n } else {\n // data.children is undefined or null - should not happen if backend is working correctly\n console.error('❌ No children data received for directory:', {\n path: searchPath,\n dataKeys: Object.keys(data),\n fullData: data\n });\n this.updateBreadcrumb(`Error loading ${node.name}`, 'error');\n this.showNotification(`Failed to load directory contents`, 'error');\n }\n this.updateStats();\n } else if (!node) {\n console.error('❌ [SUBDIRECTORY LOADING] Node not found for path:', {\n searchPath,\n originalPath: data.path,\n workingDir: this.getWorkingDirectory(),\n allTreePaths: this.getAllTreePaths(this.treeData)\n });\n this.showNotification(`Could not find directory \"${searchPath}\" in tree`, 'error');\n this.logAllPaths(this.treeData);\n } else if (node && !data.children) {\n console.warn('⚠️ [SUBDIRECTORY LOADING] Directory response has no children:', {\n path: data.path,\n searchPath,\n nodeExists: !!node,\n dataKeys: Object.keys(data),\n fullData: data\n });\n // This might be a top-level directory discovery\n const pathParts = data.path ? data.path.split('/').filter(p => p) : [];\n const isTopLevel = pathParts.length === 1;\n \n if (isTopLevel || data.forceAdd) {\n const dirNode = {\n name: data.name || pathParts[pathParts.length - 1] || 'Unknown',\n path: data.path,\n type: 'directory',\n children: [],\n loaded: false,\n expanded: false,\n stats: data.stats || {}\n };\n \n this.addNodeToTree(dirNode, data.parent || '');\n this.updateBreadcrumb(`Discovered: ${data.path}`, 'info');\n }\n }\n }\n\n /**\n * Handle file discovered event\n */\n onFileDiscovered(data) {\n // Update activity ticker\n const fileName = data.name || (data.path ? data.path.split('/').pop() : 'file');\n this.updateActivityTicker(`📄 Found: ${fileName}`);\n \n // Add to events display\n this.addEventToDisplay(`📄 Discovered: ${data.path || 'Unknown file'}`, 'info');\n \n const pathParts = data.path ? data.path.split('/').filter(p => p) : [];\n const parentPath = pathParts.slice(0, -1).join('/');\n \n const fileNode = {\n name: data.name || pathParts[pathParts.length - 1] || 'Unknown',\n path: data.path,\n type: 'file',\n language: data.language || this.detectLanguage(data.path),\n size: data.size || 0,\n lines: data.lines || 0,\n children: [],\n analyzed: false\n };\n \n this.addNodeToTree(fileNode, parentPath);\n this.stats.files++;\n this.updateStats();\n this.updateBreadcrumb(`Found: ${data.path}`, 'info');\n }\n\n /**\n * Handle file analyzed event\n */\n onFileAnalyzed(data) {\n console.log('✅ [FILE ANALYSIS] Received analysis result:', {\n path: data.path,\n elements: data.elements ? data.elements.length : 0,\n complexity: data.complexity,\n lines: data.lines,\n stats: data.stats,\n elementsDetail: data.elements,\n fullData: data\n });\n\n // Debug: Show elements in detail\n if (data.elements && data.elements.length > 0) {\n console.log('🔍 [AST ELEMENTS] Found elements:', data.elements.map(elem => ({\n name: elem.name,\n type: elem.type,\n line: elem.line,\n methods: elem.methods ? elem.methods.length : 0\n })));\n\n // Show success message with element count breakdown\n const fileName = data.path.split('/').pop();\n const elementCounts = this.getElementCounts(data.elements);\n const summary = this.formatElementSummary(elementCounts);\n\n this.showNotification(`${fileName} - ${summary}`, 'success');\n this.updateBreadcrumb(`${fileName} - AST parsed: ${summary}`, 'success');\n } else {\n const fileName = data.path.split('/').pop();\n console.log('⚠️ [AST ELEMENTS] No elements found in analysis result');\n\n // Show accurate message for files with no structural AST elements\n const fileType = this.getFileTypeDescription(fileName);\n this.showNotification(`${fileName} - No structural elements to display in tree`, 'info');\n this.updateBreadcrumb(`${fileName} - ${fileType} analyzed, content not suitable for tree view`, 'info');\n }\n\n // Clear analysis timeout\n if (this.analysisTimeouts && this.analysisTimeouts.has(data.path)) {\n clearTimeout(this.analysisTimeouts.get(data.path));\n this.analysisTimeouts.delete(data.path);\n console.log('⏰ [FILE ANALYSIS] Cleared timeout for:', data.path);\n }\n\n // Remove loading pulse if this file was being analyzed\n const d3Node = this.findD3NodeByPath(data.path);\n if (d3Node && this.loadingNodes.has(data.path)) {\n this.removeLoadingPulse(d3Node);\n this.loadingNodes.delete(data.path); // Remove from loading set\n }\n // Update activity ticker\n if (data.path) {\n const fileName = data.path.split('/').pop();\n this.updateActivityTicker(`🔍 Analyzed: ${fileName}`);\n }\n \n const fileNode = this.findNodeByPath(data.path);\n if (fileNode) {\n console.log('🔍 [FILE NODE] Found file node for:', data.path);\n fileNode.analyzed = true;\n fileNode.complexity = data.complexity || 0;\n fileNode.lines = data.lines || 0;\n\n // Add code elements as children\n if (data.elements && Array.isArray(data.elements)) {\n const children = data.elements.map(elem => ({\n name: elem.name,\n type: elem.type.toLowerCase(),\n path: `${data.path}#${elem.name}`,\n line: elem.line,\n complexity: elem.complexity || 1,\n docstring: elem.docstring || '',\n children: elem.methods ? elem.methods.map(m => ({\n name: m.name,\n type: 'method',\n path: `${data.path}#${elem.name}.${m.name}`,\n line: m.line,\n complexity: m.complexity || 1,\n docstring: m.docstring || ''\n })) : []\n }));\n\n fileNode.children = children;\n console.log('✅ [FILE NODE] Added children to file node:', {\n filePath: data.path,\n childrenCount: children.length,\n children: children.map(c => ({ name: c.name, type: c.type }))\n });\n\n // Auto-expand the file node to show AST tree if it was recently clicked\n this.autoExpandFileWithAST(data.path, fileNode);\n } else {\n console.log('⚠️ [FILE NODE] No elements to add as children');\n }\n\n // Update stats\n if (data.stats) {\n this.stats.classes += data.stats.classes || 0;\n this.stats.functions += data.stats.functions || 0;\n this.stats.methods += data.stats.methods || 0;\n this.stats.lines += data.stats.lines || 0;\n }\n\n this.updateStats();\n\n // CRITICAL FIX: Recreate D3 hierarchy to include new children\n if (this.root && fileNode.children && fileNode.children.length > 0) {\n console.log('🔄 [FILE NODE] Recreating D3 hierarchy to include AST children');\n\n // Store the old root for expansion state preservation\n const oldRoot = this.root;\n\n // Recreate the D3 hierarchy with updated data\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n\n // Preserve expansion state from old tree\n this.preserveExpansionState(oldRoot, this.root);\n\n // Find the updated file node in the new hierarchy\n const updatedFileNode = this.findD3NodeByPath(data.path);\n if (updatedFileNode) {\n // Ensure the file node is expanded to show its AST children\n if (updatedFileNode.children && updatedFileNode.children.length > 0) {\n updatedFileNode._children = null;\n updatedFileNode.data.expanded = true;\n console.log('✅ [FILE NODE] File node expanded to show AST children:', {\n path: data.path,\n childrenCount: updatedFileNode.children.length,\n childNames: updatedFileNode.children.map(c => c.data.name)\n });\n }\n }\n\n // Update the visualization with the new hierarchy\n this.update(this.root);\n } else if (this.root) {\n this.update(this.root);\n }\n\n this.updateBreadcrumb(`Analyzed: ${data.path}`, 'success');\n } else {\n console.error('❌ [FILE NODE] Could not find file node for path:', data.path);\n }\n }\n\n /**\n * Handle node found event\n */\n onNodeFound(data) {\n // Add to events display with appropriate icon\n const typeIcon = data.type === 'class' ? '🏛️' : \n data.type === 'function' ? '⚡' : \n data.type === 'method' ? '🔧' : '📦';\n this.addEventToDisplay(`${typeIcon} Found ${data.type || 'node'}: ${data.name || 'Unknown'}`);\n \n // Extract node info\n const nodeInfo = {\n name: data.name || 'Unknown',\n type: (data.type || 'unknown').toLowerCase(),\n path: data.path || '',\n line: data.line || 0,\n complexity: data.complexity || 1,\n docstring: data.docstring || ''\n };\n\n // Map event types to our internal types\n const typeMapping = {\n 'class': 'class',\n 'function': 'function',\n 'method': 'method',\n 'module': 'module',\n 'file': 'file',\n 'directory': 'directory'\n };\n\n nodeInfo.type = typeMapping[nodeInfo.type] || nodeInfo.type;\n\n // Determine parent path\n let parentPath = '';\n if (data.parent_path) {\n parentPath = data.parent_path;\n } else if (data.file_path) {\n parentPath = data.file_path;\n } else if (nodeInfo.path.includes('/')) {\n const parts = nodeInfo.path.split('/');\n parts.pop();\n parentPath = parts.join('/');\n }\n\n // Update stats based on node type\n switch(nodeInfo.type) {\n case 'class':\n this.stats.classes++;\n break;\n case 'function':\n this.stats.functions++;\n break;\n case 'method':\n this.stats.methods++;\n break;\n case 'file':\n this.stats.files++;\n break;\n }\n\n // Add node to tree\n this.addNodeToTree(nodeInfo, parentPath);\n this.updateStats();\n\n // Show progress in breadcrumb\n const elementType = nodeInfo.type.charAt(0).toUpperCase() + nodeInfo.type.slice(1);\n this.updateBreadcrumb(`Found ${elementType}: ${nodeInfo.name}`, 'info');\n }\n\n /**\n * Handle progress update\n */\n onProgressUpdate(data) {\n const progress = data.progress || 0;\n const message = data.message || `Processing... ${progress}%`;\n \n this.updateBreadcrumb(message, 'info');\n \n // Update progress bar if it exists\n const progressBar = document.querySelector('.code-tree-progress');\n if (progressBar) {\n progressBar.style.width = `${progress}%`;\n }\n }\n\n /**\n * Handle analysis complete event\n */\n onAnalysisComplete(data) {\n this.analyzing = false;\n this.hideLoading();\n \n // Update activity ticker\n this.updateActivityTicker('✅ Ready', 'success');\n \n // Add completion event\n this.addEventToDisplay('✅ Analysis complete!', 'success');\n\n // Update tree visualization\n if (this.root && this.svg) {\n this.update(this.root);\n }\n\n // Update stats from completion data\n if (data.stats) {\n this.stats = { ...this.stats, ...data.stats };\n this.updateStats();\n }\n\n const message = data.message || `Analysis complete: ${this.stats.files} files, ${this.stats.classes} classes, ${this.stats.functions} functions`;\n this.updateBreadcrumb(message, 'success');\n this.showNotification(message, 'success');\n }\n\n /**\n * Handle analysis error\n */\n onAnalysisError(data) {\n this.analyzing = false;\n this.hideLoading();\n this.loadingNodes.clear(); // Clear loading state on error\n\n const message = data.message || data.error || 'Analysis failed';\n this.updateBreadcrumb(message, 'error');\n this.showNotification(message, 'error');\n }\n\n /**\n * Handle analysis accepted\n */\n onAnalysisAccepted(data) {\n const message = data.message || 'Analysis request accepted';\n this.updateBreadcrumb(message, 'info');\n }\n\n /**\n * Handle analysis queued\n */\n onAnalysisQueued(data) {\n const position = data.position || 0;\n const message = `Analysis queued (position ${position})`;\n this.updateBreadcrumb(message, 'warning');\n this.showNotification(message, 'info');\n }\n \n /**\n * Handle INFO events for granular work tracking\n */\n onInfoEvent(data) {\n // Log to console for debugging\n \n // Update breadcrumb for certain events\n if (data.type && data.type.startsWith('discovery.')) {\n // Discovery events\n if (data.type === 'discovery.start') {\n this.updateBreadcrumb(data.message, 'info');\n } else if (data.type === 'discovery.complete') {\n this.updateBreadcrumb(data.message, 'success');\n // Show stats if available\n if (data.stats) {\n }\n } else if (data.type === 'discovery.directory' || data.type === 'discovery.file') {\n // Quick flash of discovery events\n this.updateBreadcrumb(data.message, 'info');\n }\n } else if (data.type && data.type.startsWith('analysis.')) {\n // Analysis events\n if (data.type === 'analysis.start') {\n this.updateBreadcrumb(data.message, 'info');\n } else if (data.type === 'analysis.complete') {\n this.updateBreadcrumb(data.message, 'success');\n // Show stats if available\n if (data.stats) {\n const statsMsg = `Found: ${data.stats.classes || 0} classes, ${data.stats.functions || 0} functions, ${data.stats.methods || 0} methods`;\n }\n } else if (data.type === 'analysis.class' || data.type === 'analysis.function' || data.type === 'analysis.method') {\n // Show found elements briefly\n this.updateBreadcrumb(data.message, 'info');\n } else if (data.type === 'analysis.parse') {\n this.updateBreadcrumb(data.message, 'info');\n }\n } else if (data.type && data.type.startsWith('filter.')) {\n // Filter events - optionally show in debug mode\n if (window.debugMode || this.showFilterEvents) {\n console.debug('[FILTER]', data.type, data.path, data.reason);\n if (this.showFilterEvents) {\n this.updateBreadcrumb(data.message, 'warning');\n }\n }\n } else if (data.type && data.type.startsWith('cache.')) {\n // Cache events\n if (data.type === 'cache.hit') {\n console.debug('[CACHE HIT]', data.file);\n if (this.showCacheEvents) {\n this.updateBreadcrumb(data.message, 'info');\n }\n } else if (data.type === 'cache.miss') {\n console.debug('[CACHE MISS]', data.file);\n }\n }\n \n // Optionally add to an event log display if enabled\n if (this.eventLogEnabled && data.message) {\n this.addEventToDisplay(data);\n }\n }\n \n /**\n * Add event to display log (if we have one)\n */\n addEventToDisplay(data) {\n // Could be implemented to show events in a dedicated log area\n // For now, just maintain a recent events list\n if (!this.recentEvents) {\n this.recentEvents = [];\n }\n \n this.recentEvents.unshift({\n timestamp: data.timestamp || new Date().toISOString(),\n type: data.type,\n message: data.message,\n data: data\n });\n \n // Keep only last 100 events\n if (this.recentEvents.length > 100) {\n this.recentEvents.pop();\n }\n \n // Could update a UI element here if we had an event log display\n }\n\n /**\n * Handle analysis cancelled\n */\n onAnalysisCancelled(data) {\n this.analyzing = false;\n this.hideLoading();\n this.loadingNodes.clear(); // Clear loading state on cancellation\n const message = data.message || 'Analysis cancelled';\n this.updateBreadcrumb(message, 'warning');\n }\n\n /**\n * Show notification toast\n */\n showNotification(message, type = 'info') {\n const notification = document.createElement('div');\n notification.className = `code-tree-notification ${type}`;\n notification.textContent = message;\n \n // Change from appending to container to positioning absolutely within it\n const container = document.getElementById('code-tree-container');\n if (container) {\n // Position relative to the container\n notification.style.position = 'absolute';\n notification.style.top = '10px';\n notification.style.right = '10px';\n notification.style.zIndex = '1000';\n \n // Ensure container is positioned\n if (!container.style.position || container.style.position === 'static') {\n container.style.position = 'relative';\n }\n \n container.appendChild(notification);\n \n // Animate out after 3 seconds\n setTimeout(() => {\n notification.style.animation = 'slideOutRight 0.3s ease';\n setTimeout(() => notification.remove(), 300);\n }, 3000);\n }\n }\n\n /**\n * Add node to tree structure\n */\n addNodeToTree(nodeInfo, parentPath = '') {\n // CRITICAL: Validate that nodeInfo.path doesn't contain absolute paths\n // The backend should only send relative paths now\n if (nodeInfo.path && nodeInfo.path.startsWith('/')) {\n console.error('Absolute path detected in node, skipping:', nodeInfo.path);\n return;\n }\n \n // Also validate parent path\n if (parentPath && parentPath.startsWith('/')) {\n console.error('Absolute path detected in parent, skipping:', parentPath);\n return;\n }\n \n // Find parent node\n let parentNode = this.treeData;\n \n if (parentPath) {\n parentNode = this.findNodeByPath(parentPath);\n if (!parentNode) {\n // CRITICAL: Do NOT create parent structure if it doesn't exist\n // This prevents creating nodes above the working directory\n console.warn('Parent node not found, skipping node creation:', parentPath);\n console.warn('Attempted to add node:', nodeInfo);\n return;\n }\n }\n\n // Check if node already exists\n const existingNode = parentNode.children?.find(c => \n c.path === nodeInfo.path || \n (c.name === nodeInfo.name && c.type === nodeInfo.type)\n );\n\n if (existingNode) {\n // Update existing node\n Object.assign(existingNode, nodeInfo);\n return;\n }\n\n // Add new node\n if (!parentNode.children) {\n parentNode.children = [];\n }\n \n // Ensure the node has a children array\n if (!nodeInfo.children) {\n nodeInfo.children = [];\n }\n \n parentNode.children.push(nodeInfo);\n\n // Store node reference for quick access\n this.nodes.set(nodeInfo.path, nodeInfo);\n\n // Update tree if initialized\n if (this.root && this.svg) {\n // Recreate hierarchy with new data\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n // Update only if we have a reasonable number of nodes to avoid performance issues\n if (this.nodes.size < 1000) {\n this.update(this.root);\n } else if (this.nodes.size % 100 === 0) {\n // Update every 100 nodes for large trees\n this.update(this.root);\n }\n }\n }\n\n /**\n * Find node by path in tree\n */\n findNodeByPath(path, node = null) {\n if (!node) {\n node = this.treeData;\n console.log('🔍 [SUBDIRECTORY LOADING] Starting search for path:', path);\n }\n\n if (node.path === path) {\n console.log('✅ [SUBDIRECTORY LOADING] Found node for path:', path);\n return node;\n }\n\n if (node.children) {\n for (const child of node.children) {\n const found = this.findNodeByPath(path, child);\n if (found) {\n return found;\n }\n }\n }\n\n if (!node.parent && node === this.treeData) {\n console.warn('❌ [SUBDIRECTORY LOADING] Path not found in tree:', path);\n }\n return null;\n }\n \n /**\n * Helper to log all paths in tree for debugging\n */\n logAllPaths(node, indent = '') {\n console.log(`${indent}${node.path} (${node.name})`);\n if (node.children) {\n for (const child of node.children) {\n this.logAllPaths(child, indent + ' ');\n }\n }\n }\n \n /**\n * Helper to collect all paths in tree for debugging\n */\n getAllTreePaths(node) {\n const paths = [node.path];\n if (node.children) {\n for (const child of node.children) {\n paths.push(...this.getAllTreePaths(child));\n }\n }\n return paths;\n }\n \n /**\n * Find D3 hierarchy node by path\n */\n findD3NodeByPath(path) {\n if (!this.root) return null;\n return this.root.descendants().find(d => d.data.path === path);\n }\n \n /**\n * Preserve expansion state when recreating hierarchy\n */\n preserveExpansionState(oldRoot, newRoot) {\n if (!oldRoot || !newRoot) return;\n \n // Create a map of expanded nodes from the old tree\n const expansionMap = new Map();\n oldRoot.descendants().forEach(node => {\n if (node.data.expanded || (node.children && !node._children)) {\n expansionMap.set(node.data.path, true);\n }\n });\n \n // Apply expansion state to new tree\n newRoot.descendants().forEach(node => {\n if (expansionMap.has(node.data.path)) {\n node.children = node._children || node.children;\n node._children = null;\n node.data.expanded = true;\n }\n });\n }\n\n /**\n * Update statistics display\n */\n updateStats() {\n // Update stats display - use correct IDs from corner controls\n const statsElements = {\n 'stats-files': this.stats.files,\n 'stats-classes': this.stats.classes,\n 'stats-functions': this.stats.functions,\n 'stats-methods': this.stats.methods\n };\n\n for (const [id, value] of Object.entries(statsElements)) {\n const elem = document.getElementById(id);\n if (elem) {\n elem.textContent = value.toLocaleString();\n }\n }\n\n // Update progress text\n const progressText = document.getElementById('code-progress-text');\n if (progressText) {\n const statusText = this.analyzing ? \n `Analyzing... ${this.stats.files} files processed` : \n `Ready - ${this.stats.files} files in tree`;\n progressText.textContent = statusText;\n }\n }\n\n /**\n * Update breadcrumb trail\n */\n updateBreadcrumb(message, type = 'info') {\n const breadcrumbContent = document.getElementById('breadcrumb-content');\n if (breadcrumbContent) {\n breadcrumbContent.textContent = message;\n breadcrumbContent.className = `breadcrumb-${type}`;\n }\n }\n\n /**\n * Analyze file using HTTP fallback when SocketIO fails\n */\n async analyzeFileHTTP(filePath, fileName, d3Node) {\n console.log('🌐 [HTTP FALLBACK] Analyzing file via HTTP:', filePath);\n console.log('🌐 [HTTP FALLBACK] File name:', fileName);\n\n try {\n // For now, create mock AST data since we don't have an HTTP endpoint yet\n // This demonstrates the structure and can be replaced with real HTTP call\n const mockAnalysisResult = this.createMockAnalysisData(filePath, fileName);\n console.log('🌐 [HTTP FALLBACK] Created mock data:', mockAnalysisResult);\n\n // Simulate network delay\n setTimeout(() => {\n console.log('✅ [HTTP FALLBACK] Mock analysis complete for:', fileName);\n console.log('✅ [HTTP FALLBACK] Calling onFileAnalyzed with:', mockAnalysisResult);\n this.onFileAnalyzed(mockAnalysisResult);\n }, 1000);\n\n } catch (error) {\n console.error('❌ [HTTP FALLBACK] Analysis failed:', error);\n this.showNotification(`Analysis failed: ${error.message}`, 'error');\n this.loadingNodes.delete(filePath);\n this.removeLoadingPulse(d3Node);\n }\n }\n\n /**\n * Create mock analysis data for demonstration\n */\n createMockAnalysisData(filePath, fileName) {\n const ext = fileName.split('.').pop()?.toLowerCase();\n console.log('🔍 [MOCK DATA] Creating mock data for file:', fileName, 'extension:', ext);\n\n // Create realistic mock data based on file type\n let elements = [];\n\n if (ext === 'py') {\n elements = [\n {\n name: 'ExampleClass',\n type: 'class',\n line: 10,\n complexity: 3,\n docstring: 'Example class for demonstration',\n methods: [\n { name: '__init__', type: 'method', line: 12, complexity: 1 },\n { name: 'example_method', type: 'method', line: 18, complexity: 2 }\n ]\n },\n {\n name: 'example_function',\n type: 'function',\n line: 25,\n complexity: 2,\n docstring: 'Example function'\n }\n ];\n } else if (ext === 'js' || ext === 'ts') {\n elements = [\n {\n name: 'ExampleClass',\n type: 'class',\n line: 5,\n complexity: 2,\n methods: [\n { name: 'constructor', type: 'method', line: 6, complexity: 1 },\n { name: 'exampleMethod', type: 'method', line: 10, complexity: 2 }\n ]\n },\n {\n name: 'exampleFunction',\n type: 'function',\n line: 20,\n complexity: 1\n }\n ];\n } else {\n // For other file types, create at least one element to show it's working\n elements = [\n {\n name: 'mock_element',\n type: 'function',\n line: 1,\n complexity: 1,\n docstring: `Mock element for ${fileName}`\n }\n ];\n }\n\n console.log('🔍 [MOCK DATA] Created elements:', elements);\n\n return {\n path: filePath,\n elements: elements,\n complexity: elements.reduce((sum, elem) => sum + (elem.complexity || 1), 0),\n lines: 50,\n stats: {\n classes: elements.filter(e => e.type === 'class').length,\n functions: elements.filter(e => e.type === 'function').length,\n methods: elements.reduce((sum, e) => sum + (e.methods ? e.methods.length : 0), 0),\n lines: 50\n }\n };\n }\n\n /**\n * Get selected languages from checkboxes with fallback\n */\n getSelectedLanguages() {\n const selectedLanguages = [];\n const checkboxes = document.querySelectorAll('.language-checkbox:checked');\n\n console.log('🔍 [LANGUAGE] Found checkboxes:', checkboxes.length);\n console.log('🔍 [LANGUAGE] All language checkboxes:', document.querySelectorAll('.language-checkbox').length);\n\n checkboxes.forEach(cb => {\n console.log('🔍 [LANGUAGE] Checked language:', cb.value);\n selectedLanguages.push(cb.value);\n });\n\n // Fallback: if no languages are selected, default to common ones\n if (selectedLanguages.length === 0) {\n console.warn('⚠️ [LANGUAGE] No languages selected, using defaults');\n selectedLanguages.push('python', 'javascript', 'typescript');\n\n // Also check the checkboxes programmatically\n document.querySelectorAll('.language-checkbox').forEach(cb => {\n if (['python', 'javascript', 'typescript'].includes(cb.value)) {\n cb.checked = true;\n console.log('✅ [LANGUAGE] Auto-checked:', cb.value);\n }\n });\n }\n\n return selectedLanguages;\n }\n\n /**\n * Detect language from file extension\n */\n detectLanguage(filePath) {\n const ext = filePath.split('.').pop().toLowerCase();\n const languageMap = {\n 'py': 'python',\n 'js': 'javascript',\n 'ts': 'typescript',\n 'jsx': 'javascript',\n 'tsx': 'typescript',\n 'java': 'java',\n 'cpp': 'cpp',\n 'c': 'c',\n 'cs': 'csharp',\n 'rb': 'ruby',\n 'go': 'go',\n 'rs': 'rust',\n 'php': 'php',\n 'swift': 'swift',\n 'kt': 'kotlin',\n 'scala': 'scala',\n 'r': 'r',\n 'sh': 'bash',\n 'ps1': 'powershell'\n };\n return languageMap[ext] || 'unknown';\n }\n\n /**\n * Add visualization controls for layout toggle\n */\n addVisualizationControls() {\n const controls = this.svg.append('g')\n .attr('class', 'viz-controls')\n .attr('transform', 'translate(10, 10)');\n \n // Add layout toggle button\n const toggleButton = controls.append('g')\n .attr('class', 'layout-toggle')\n .style('cursor', 'pointer')\n .on('click', () => this.toggleLayout());\n \n toggleButton.append('rect')\n .attr('width', 120)\n .attr('height', 30)\n .attr('rx', 5)\n .attr('fill', '#3b82f6')\n .attr('opacity', 0.8);\n \n toggleButton.append('text')\n .attr('x', 60)\n .attr('y', 20)\n .attr('text-anchor', 'middle')\n .attr('fill', 'white')\n .style('font-size', '12px')\n .text(this.isRadialLayout ? 'Switch to Linear' : 'Switch to Radial');\n }\n \n /**\n * Toggle between radial and linear layouts\n */\n toggleLayout() {\n this.isRadialLayout = !this.isRadialLayout;\n this.createVisualization();\n if (this.root) {\n this.update(this.root);\n }\n this.showNotification(\n this.isRadialLayout ? 'Switched to radial layout' : 'Switched to linear layout',\n 'info'\n );\n }\n\n /**\n * Convert radial coordinates to Cartesian\n */\n radialPoint(x, y) {\n return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];\n }\n\n /**\n * Apply horizontal text to the central spine of the tree\n */\n applySingletonHorizontalLayout(nodes) {\n if (this.isRadialLayout) return; // Only apply to linear layout\n\n // Clear previous horizontal nodes tracking\n this.horizontalNodes.clear();\n this.centralSpine.clear();\n\n // Find the central spine - the main path through the tree\n this.identifyCentralSpine(nodes);\n\n // Mark all central spine nodes for horizontal text\n this.centralSpine.forEach(path => {\n this.horizontalNodes.add(path);\n });\n\n console.log(`🎯 [SPINE] Central spine nodes:`, Array.from(this.centralSpine));\n console.log(`📝 [TEXT] Horizontal text nodes:`, Array.from(this.horizontalNodes));\n }\n\n /**\n * Identify the central spine of the tree (main path from root to deepest/most important nodes)\n */\n identifyCentralSpine(nodes) {\n if (!nodes || nodes.length === 0) return;\n\n // Start with the root node\n const rootNode = nodes.find(node => node.depth === 0);\n if (!rootNode) {\n console.warn('🎯 [SPINE] No root node found!');\n return;\n }\n\n this.centralSpine.add(rootNode.data.path);\n console.log(`🎯 [SPINE] Starting spine with root: ${rootNode.data.name} (${rootNode.data.path})`);\n\n // Follow the main path through the tree\n let currentNode = rootNode;\n while (currentNode && currentNode.children && currentNode.children.length > 0) {\n // Choose the \"main\" child - prioritize directories, then by name\n const mainChild = this.selectMainChild(currentNode.children);\n if (mainChild) {\n this.centralSpine.add(mainChild.data.path);\n console.log(`🎯 [SPINE] Adding to spine: ${mainChild.data.name}`);\n currentNode = mainChild;\n } else {\n break;\n }\n }\n }\n\n /**\n * Select the main child to continue the central spine\n */\n selectMainChild(children) {\n if (!children || children.length === 0) return null;\n\n // If only one child, it's the main path\n if (children.length === 1) return children[0];\n\n // Prioritize directories over files\n const directories = children.filter(child => this.isNodeDirectory(child));\n if (directories.length === 1) return directories[0];\n\n // If multiple directories, choose the first one (could be enhanced with better logic)\n if (directories.length > 0) return directories[0];\n\n // Fallback to first child\n return children[0];\n }\n\n /**\n * Find chains of singleton nodes (nodes with only one child)\n */\n findSingletonChains(nodes) {\n const chains = [];\n const processed = new Set();\n\n nodes.forEach(node => {\n if (processed.has(node)) return;\n\n // Start a new chain if this node has exactly one child\n if (node.children && node.children.length === 1) {\n const chain = [node];\n let current = node.children[0];\n\n console.log(`🔍 [CHAIN] Starting singleton chain with: ${node.data.name} (depth: ${node.depth})`);\n\n // Follow the chain of singletons\n while (current && current.children && current.children.length === 1) {\n chain.push(current);\n processed.add(current);\n console.log(`🔍 [CHAIN] Adding to chain: ${current.data.name} (depth: ${current.depth})`);\n current = current.children[0];\n }\n\n // Add the final node if it exists (even if it has multiple children or no children)\n if (current) {\n chain.push(current);\n processed.add(current);\n console.log(`🔍 [CHAIN] Final node in chain: ${current.data.name} (depth: ${current.depth})`);\n }\n\n // Only create horizontal layout for chains of 2 or more nodes\n if (chain.length >= 2) {\n console.log(`✅ [CHAIN] Created horizontal chain:`, chain.map(n => n.data.name));\n chains.push(chain);\n processed.add(node);\n } else {\n console.log(`❌ [CHAIN] Chain too short (${chain.length}), skipping`);\n }\n }\n });\n\n return chains;\n }\n\n /**\n * Layout a chain of nodes horizontally with parent in center\n */\n layoutChainHorizontally(chain) {\n if (chain.length < 2) return;\n\n const horizontalSpacing = 150; // Spacing between nodes in horizontal chain\n const parentNode = chain[0];\n const originalX = parentNode.x;\n const originalY = parentNode.y;\n\n // CRITICAL: In D3 tree layout for linear mode:\n // - d.x controls VERTICAL position (up-down)\n // - d.y controls HORIZONTAL position (left-right)\n // To make singleton chains horizontal, we need to adjust d.x (vertical) to be the same\n // and spread out d.y (horizontal) positions\n\n if (chain.length === 2) {\n // Simple case: parent and one child side by side\n const centerY = originalY;\n parentNode.y = centerY - horizontalSpacing / 2; // Parent to the left\n chain[1].y = centerY + horizontalSpacing / 2; // Child to the right\n chain[1].x = originalX; // Same vertical level as parent\n } else {\n // Multiple nodes: center the parent in the horizontal chain\n const totalWidth = (chain.length - 1) * horizontalSpacing;\n const startY = originalY - (totalWidth / 2);\n\n chain.forEach((node, index) => {\n node.y = startY + (index * horizontalSpacing); // Spread horizontally\n node.x = originalX; // All at same vertical level\n });\n }\n\n // Mark all nodes in this chain as needing horizontal text\n chain.forEach(node => {\n this.horizontalNodes.add(node.data.path);\n console.log(`📝 [TEXT] Marking node for horizontal text: ${node.data.name} (${node.data.path})`);\n });\n\n console.log(`🔄 [LAYOUT] Horizontal chain of ${chain.length} nodes:`,\n chain.map(n => ({ name: n.data.name, vertical: n.x, horizontal: n.y })));\n console.log(`📝 [TEXT] Total horizontal nodes:`, Array.from(this.horizontalNodes));\n }\n\n\n\n /**\n * Update D3 tree visualization\n */\n update(source) {\n if (!this.treeLayout || !this.treeGroup || !source) {\n return;\n }\n\n // Compute the new tree layout\n const treeData = this.treeLayout(this.root);\n const nodes = treeData.descendants();\n const links = treeData.descendants().slice(1);\n\n // Apply horizontal layout for singleton chains\n this.applySingletonHorizontalLayout(nodes);\n\n if (this.isRadialLayout) {\n // Radial layout adjustments\n nodes.forEach(d => {\n // Store original x,y for transitions\n if (d.x0 === undefined) {\n d.x0 = d.x;\n d.y0 = d.y;\n }\n });\n } else {\n // Linear layout with nodeSize doesn't need manual normalization\n // The tree layout handles spacing automatically\n }\n\n // Update nodes\n const node = this.treeGroup.selectAll('g.node')\n .data(nodes, d => d.id || (d.id = ++this.nodeId));\n\n // Enter new nodes\n const nodeEnter = node.enter().append('g')\n .attr('class', d => {\n let classes = ['node', 'code-node'];\n if (this.isNodeDirectory(d)) {\n classes.push('directory');\n if (d.data.loaded === true && d.children) {\n classes.push('expanded');\n }\n if (d.data.loaded === 'loading') {\n classes.push('loading');\n }\n if (d.data.children && d.data.children.length === 0) {\n classes.push('empty');\n }\n } else if (d.data.type === 'file') {\n classes.push('file');\n }\n return classes.join(' ');\n })\n .attr('transform', d => {\n if (this.isRadialLayout) {\n const [x, y] = this.radialPoint(source.x0 || 0, source.y0 || 0);\n return `translate(${x},${y})`;\n } else {\n return `translate(${source.y0},${source.x0})`;\n }\n })\n .on('click', (event, d) => {\n console.log('🔴 [G-ELEMENT] Click on node group element!', {\n nodeName: d?.data?.name,\n nodePath: d?.data?.path,\n eventTarget: event.target.tagName,\n thisContext: this,\n hasOnNodeClick: typeof this.onNodeClick === 'function'\n });\n // Use bound method\n this.onNodeClick(event, d);\n });\n\n // Add circles for nodes\n nodeEnter.append('circle')\n .attr('class', 'node-circle')\n .attr('r', 1e-6)\n .style('fill', d => this.getNodeColor(d))\n .style('stroke', d => this.getNodeStrokeColor(d))\n .style('stroke-width', d => this.isNodeDirectory(d) ? 2 : 1.5)\n .style('cursor', d => (d.data && (d.data.type === 'root' || d.data.isRoot || d.depth === 0)) ? 'default' : 'pointer') // No pointer for root\n .on('click', (event, d) => {\n console.log('🔵 [CIRCLE] Click on circle element!', {\n nodeName: d?.data?.name,\n nodePath: d?.data?.path,\n hasOnNodeClick: typeof this.onNodeClick === 'function'\n });\n // Use bound method\n this.onNodeClick(event, d);\n }) // CRITICAL FIX: Add click handler to circles\n .on('mouseover', this.showTooltip)\n .on('mouseout', this.hideTooltip);\n \n // Add expand/collapse icons for directories\n nodeEnter.filter(d => this.isNodeDirectory(d))\n .append('text')\n .attr('class', 'expand-icon')\n .attr('x', 0)\n .attr('y', 0)\n .attr('text-anchor', 'middle')\n .attr('dominant-baseline', 'central')\n .text(d => {\n if (d.data.loaded === 'loading') return '⟳';\n if (d.data.loaded === true && d.children) return '▼';\n return '▶';\n })\n .style('font-size', '10px')\n .style('pointer-events', 'none');\n\n // Add labels for nodes with smart positioning\n nodeEnter.append('text')\n .attr('class', d => {\n // Add horizontal-text class for root node\n const baseClass = 'node-label';\n if (d.depth === 0) {\n console.log(`📝 [TEXT] ✅ Adding horizontal-text class to root: ${d.data.name}`);\n return `${baseClass} horizontal-text`;\n }\n return baseClass;\n })\n .attr('dy', '.35em')\n .attr('x', d => {\n if (this.isRadialLayout) {\n // For radial layout, initial position\n return 0;\n } else if (d.depth === 0 || this.horizontalNodes.has(d.data.path)) {\n // Root node or horizontal nodes: center text above the node\n console.log(`📝 [TEXT] ✅ HORIZONTAL positioning for: ${d.data.name} (depth: ${d.depth}, path: ${d.data.path})`);\n console.log(`📝 [TEXT] ✅ Root check: depth === 0 = ${d.depth === 0}`);\n console.log(`📝 [TEXT] ✅ Horizontal set check: ${this.horizontalNodes.has(d.data.path)}`);\n return 0;\n } else {\n // Linear layout: standard positioning\n console.log(`📝 [TEXT] Positioning vertical text for: ${d.data.name} (depth: ${d.depth}, path: ${d.data.path})`);\n return d.children || d._children ? -13 : 13;\n }\n })\n .attr('y', d => {\n // For root node or horizontal nodes, position text above the node\n return (d.depth === 0 || this.horizontalNodes.has(d.data.path)) ? -20 : 0;\n })\n .attr('text-anchor', d => {\n if (this.isRadialLayout) {\n return 'start'; // Will be adjusted in update\n } else if (d.depth === 0 || this.horizontalNodes.has(d.data.path)) {\n // Root node or horizontal nodes: center the text\n return 'middle';\n } else {\n // Linear layout: standard anchoring\n return d.children || d._children ? 'end' : 'start';\n }\n })\n .text(d => {\n // Truncate long names\n const maxLength = 20;\n const name = d.data.name || '';\n return name.length > maxLength ? \n name.substring(0, maxLength - 3) + '...' : name;\n })\n .style('fill-opacity', 1e-6)\n .style('font-size', '12px')\n .style('font-family', '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif')\n .style('text-shadow', '1px 1px 2px rgba(255,255,255,0.8), -1px -1px 2px rgba(255,255,255,0.8)')\n .style('writing-mode', d => {\n // Force horizontal writing mode for root node\n if (d.depth === 0) {\n console.log(`📝 [TEXT] ✅ Setting horizontal writing-mode for root: ${d.data.name}`);\n return 'horizontal-tb';\n }\n return null;\n })\n .style('text-orientation', d => {\n // Force mixed text orientation for root node\n if (d.depth === 0) {\n console.log(`📝 [TEXT] ✅ Setting mixed text-orientation for root: ${d.data.name}`);\n return 'mixed';\n }\n return null;\n })\n .on('click', (event, d) => {\n console.log('📝 [LABEL] Click on text label!', {\n nodeName: d?.data?.name,\n nodePath: d?.data?.path,\n hasOnNodeClick: typeof this.onNodeClick === 'function'\n });\n // Use bound method\n this.onNodeClick(event, d);\n }) // CRITICAL FIX: Add click handler to labels\n .style('cursor', d => (d.data && (d.data.type === 'root' || d.data.isRoot || d.depth === 0)) ? 'default' : 'pointer');\n\n // Add icons for node types (files only, directories use expand icons)\n nodeEnter.filter(d => !this.isNodeDirectory(d))\n .append('text')\n .attr('class', 'node-icon')\n .attr('dy', '.35em')\n .attr('x', 0)\n .attr('text-anchor', 'middle')\n .text(d => this.getNodeIcon(d))\n .style('font-size', '10px')\n .style('fill', 'white')\n .on('click', this.onNodeClick) // CRITICAL FIX: Add click handler to file icons\n .style('cursor', 'pointer');\n \n // Add item count badges for directories\n nodeEnter.filter(d => this.isNodeDirectory(d) && d.data.children)\n .append('text')\n .attr('class', 'item-count-badge')\n .attr('x', 12)\n .attr('y', -8)\n .attr('text-anchor', 'middle')\n .text(d => {\n const count = d.data.children ? d.data.children.length : 0;\n return count > 0 ? count : '';\n })\n .style('font-size', '9px')\n .style('opacity', 0.7)\n .on('click', this.onNodeClick) // CRITICAL FIX: Add click handler to count badges\n .style('cursor', 'pointer');\n\n // Transition to new positions\n const nodeUpdate = nodeEnter.merge(node);\n\n // CRITICAL FIX: Ensure ALL nodes (new and existing) have click handlers\n // This fixes the issue where subdirectory clicks stop working after tree updates\n nodeUpdate.on('click', (event, d) => {\n console.log('🟡 [NODE-UPDATE] Click on updated node!', {\n nodeName: d?.data?.name,\n nodePath: d?.data?.path,\n hasOnNodeClick: typeof this.onNodeClick === 'function',\n thisContext: this\n });\n // Use bound method\n this.onNodeClick(event, d);\n });\n \n // ADDITIONAL FIX: Also ensure click handlers on all child elements using bound methods\n nodeUpdate.selectAll('circle').on('click', this.onNodeClick);\n nodeUpdate.selectAll('text').on('click', this.onNodeClick);\n\n nodeUpdate.transition()\n .duration(this.duration)\n .attr('transform', d => {\n if (this.isRadialLayout) {\n const [x, y] = this.radialPoint(d.x, d.y);\n return `translate(${x},${y})`;\n } else {\n return `translate(${d.y},${d.x})`;\n }\n });\n\n // Update node classes based on current state\n nodeUpdate.attr('class', d => {\n let classes = ['node', 'code-node'];\n if (this.isNodeDirectory(d)) {\n classes.push('directory');\n if (d.data.loaded === true && d.children) {\n classes.push('expanded');\n }\n if (d.data.loaded === 'loading') {\n classes.push('loading');\n }\n if (d.data.children && d.data.children.length === 0) {\n classes.push('empty');\n }\n } else if (d.data.type === 'file') {\n classes.push('file');\n }\n return classes.join(' ');\n });\n \n nodeUpdate.select('circle.node-circle')\n .attr('r', d => this.isNodeDirectory(d) ? 10 : 8)\n .style('fill', d => this.getNodeColor(d))\n \n // Update expand/collapse icons\n nodeUpdate.select('.expand-icon')\n .text(d => {\n if (d.data.loaded === 'loading') return '⟳';\n if (d.data.loaded === true && d.children) return '▼';\n return '▶';\n });\n \n // Update item count badges\n nodeUpdate.select('.item-count-badge')\n .text(d => {\n if (!this.isNodeDirectory(d)) return '';\n const count = d.data.children ? d.data.children.length : 0;\n return count > 0 ? count : '';\n })\n .style('stroke', d => this.getNodeStrokeColor(d))\n .attr('cursor', 'pointer');\n\n // Update text labels with proper rotation for radial layout\n const isRadial = this.isRadialLayout; // Capture the layout type\n const horizontalNodes = this.horizontalNodes; // Capture horizontal nodes set\n nodeUpdate.select('text.node-label')\n .style('fill-opacity', 1)\n .style('fill', '#333')\n .each(function(d) {\n const selection = d3.select(this);\n \n if (isRadial) {\n // For radial layout, apply rotation and positioning\n const angle = (d.x * 180 / Math.PI) - 90; // Convert to degrees\n \n // Determine if text should be flipped (left side of circle)\n const shouldFlip = angle > 90 || angle < -90;\n \n // Calculate text position and rotation\n if (shouldFlip) {\n // Text on left side - rotate 180 degrees to read properly\n selection\n .attr('transform', `rotate(${angle + 180})`)\n .attr('x', -15) // Negative offset for flipped text\n .attr('text-anchor', 'end')\n .attr('dy', '.35em');\n } else {\n // Text on right side - normal orientation\n selection\n .attr('transform', `rotate(${angle})`)\n .attr('x', 15) // Positive offset for normal text\n .attr('text-anchor', 'start')\n .attr('dy', '.35em');\n }\n } else {\n // Linear layout - handle root node and horizontal nodes differently\n const isHorizontal = d.depth === 0 || horizontalNodes.has(d.data.path);\n\n if (isHorizontal) {\n // Root node or horizontal nodes: text above the node, centered\n selection\n .attr('transform', null)\n .attr('x', 0)\n .attr('y', -20)\n .attr('text-anchor', 'middle')\n .attr('dy', '.35em');\n } else {\n // Regular linear layout - no rotation needed\n selection\n .attr('transform', null)\n .attr('x', d.children || d._children ? -13 : 13)\n .attr('y', 0)\n .attr('text-anchor', d.children || d._children ? 'end' : 'start')\n .attr('dy', '.35em');\n }\n }\n });\n\n // Remove exiting nodes\n const nodeExit = node.exit().transition()\n .duration(this.duration)\n .attr('transform', d => {\n if (this.isRadialLayout) {\n const [x, y] = this.radialPoint(source.x, source.y);\n return `translate(${x},${y})`;\n } else {\n return `translate(${source.y},${source.x})`;\n }\n })\n .remove();\n\n nodeExit.select('circle')\n .attr('r', 1e-6);\n\n nodeExit.select('text.node-label')\n .style('fill-opacity', 1e-6);\n \n nodeExit.select('text.node-icon')\n .style('fill-opacity', 1e-6);\n\n // Update links\n const link = this.treeGroup.selectAll('path.link')\n .data(links, d => d.id);\n\n // Enter new links\n const linkEnter = link.enter().insert('path', 'g')\n .attr('class', 'link')\n .attr('d', d => {\n const o = {x: source.x0, y: source.y0};\n return this.isRadialLayout ? \n this.radialDiagonal(o, o) : \n this.diagonal(o, o);\n })\n .style('fill', 'none')\n .style('stroke', '#ccc')\n .style('stroke-width', 2);\n\n // Transition to new positions\n const linkUpdate = linkEnter.merge(link);\n\n linkUpdate.transition()\n .duration(this.duration)\n .attr('d', d => this.isRadialLayout ? \n this.radialDiagonal(d, d.parent) : \n this.diagonal(d, d.parent));\n\n // Remove exiting links\n link.exit().transition()\n .duration(this.duration)\n .attr('d', d => {\n const o = {x: source.x, y: source.y};\n return this.isRadialLayout ? \n this.radialDiagonal(o, o) : \n this.diagonal(o, o);\n })\n .remove();\n\n // Store old positions for transition\n nodes.forEach(d => {\n d.x0 = d.x;\n d.y0 = d.y;\n });\n\n // Apply current zoom level to maintain consistent text size\n if (this.zoom) {\n const currentTransform = d3.zoomTransform(this.svg.node());\n if (currentTransform.k !== 1) {\n this.adjustTextSizeForZoom(currentTransform.k);\n }\n }\n }\n\n /**\n * REMOVED: Center the view on a specific node (Linear layout)\n * This method has been completely disabled to prevent unwanted tree movement.\n * All centering functionality has been removed from the code tree.\n */\n centerOnNode(d) {\n // Method disabled - no centering operations will be performed\n console.log('[CodeTree] centerOnNode called but disabled - no centering will occur');\n return;\n }\n \n /**\n * REMOVED: Center the view on a specific node (Radial layout)\n * This method has been completely disabled to prevent unwanted tree movement.\n * All centering functionality has been removed from the code tree.\n */\n centerOnNodeRadial(d) {\n // Method disabled - no centering operations will be performed\n console.log('[CodeTree] centerOnNodeRadial called but disabled - no centering will occur');\n return;\n }\n \n /**\n * Highlight the active node with larger icon\n */\n highlightActiveNode(d) {\n // Reset all nodes to normal size and clear parent context\n // First clear classes on the selection\n const allCircles = this.treeGroup.selectAll('circle.node-circle');\n allCircles\n .classed('active', false)\n .classed('parent-context', false);\n \n // Then apply transition separately\n allCircles\n .transition()\n .duration(300)\n .attr('r', 8)\n .style('stroke', null)\n .style('stroke-width', null)\n .style('opacity', null);\n \n // Reset all labels to normal\n this.treeGroup.selectAll('text.node-label')\n .style('font-weight', 'normal')\n .style('font-size', '12px');\n \n // Find and increase size of clicked node - use data matching\n // Make the size increase MUCH more dramatic: 8 -> 20 (2.5x the size)\n const activeNodeCircle = this.treeGroup.selectAll('g.node')\n .filter(node => node === d)\n .select('circle.node-circle');\n \n // First set the class (not part of transition)\n activeNodeCircle.classed('active', true);\n \n // Then apply the transition with styles - MUCH LARGER\n activeNodeCircle\n .transition()\n .duration(300)\n .attr('r', 20) // Much larger radius (2.5x)\n .style('stroke', '#3b82f6')\n .style('stroke-width', 5) // Thicker border\n .style('filter', 'drop-shadow(0 0 15px rgba(59, 130, 246, 0.6))'); // Stronger glow effect\n \n // Also make the label bold\n this.treeGroup.selectAll('g.node')\n .filter(node => node === d)\n .select('text.node-label')\n .style('font-weight', 'bold')\n .style('font-size', '14px'); // Slightly larger text\n \n // Store active node\n this.activeNode = d;\n }\n \n /**\n * Add pulsing animation for loading state\n */\n addLoadingPulse(d) {\n // Use consistent selection pattern\n const node = this.treeGroup.selectAll('g.node')\n .filter(node => node === d)\n .select('circle.node-circle');\n \n // Add to loading set\n this.loadingNodes.add(d.data.path);\n \n // Add pulsing class and orange color - separate operations\n node.classed('loading-pulse', true);\n node.style('fill', '#fb923c'); // Orange color for loading\n \n // Create pulse animation\n const pulseAnimation = () => {\n if (!this.loadingNodes.has(d.data.path)) return;\n \n node.transition()\n .duration(600)\n .attr('r', 14)\n .style('opacity', 0.6)\n .transition()\n .duration(600)\n .attr('r', 10)\n .style('opacity', 1)\n .on('end', () => {\n if (this.loadingNodes.has(d.data.path)) {\n pulseAnimation(); // Continue pulsing\n }\n });\n };\n \n pulseAnimation();\n }\n \n /**\n * Remove pulsing animation when loading complete\n * Note: This function only handles visual animation removal.\n * The caller is responsible for managing the loadingNodes Set.\n */\n removeLoadingPulse(d) {\n // Note: loadingNodes.delete() is handled by the caller for explicit control\n \n // Use consistent selection pattern\n const node = this.treeGroup.selectAll('g.node')\n .filter(node => node === d)\n .select('circle.node-circle');\n \n // Clear class first\n node.classed('loading-pulse', false);\n \n // Then interrupt and transition\n node.interrupt() // Stop animation\n .transition()\n .duration(300)\n .attr('r', this.activeNode === d ? 20 : 8) // Use 20 for active node\n .style('opacity', 1)\n .style('fill', d => this.getNodeColor(d)); // Restore original color\n }\n \n /**\n * Show parent node alongside for context\n */\n showWithParent(d) {\n if (!d.parent) return;\n \n // Make parent more visible\n const parentNode = this.treeGroup.selectAll('g.node')\n .filter(node => node === d.parent);\n \n // Highlight parent with different style - separate class from styles\n const parentCircle = parentNode.select('circle.node-circle');\n parentCircle.classed('parent-context', true);\n parentCircle\n .style('stroke', '#10b981')\n .style('stroke-width', 3)\n .style('opacity', 0.8);\n \n // REMOVED: Radial zoom adjustment functionality\n // This section previously adjusted zoom to show parent and clicked node together,\n // but has been completely disabled to prevent unwanted tree movement/centering.\n // Only visual highlighting of the parent remains active.\n \n // if (this.isRadialLayout && d.parent) {\n // // All zoom.transform operations have been disabled\n // // to prevent tree movement when nodes are clicked\n // }\n }\n \n /**\n * Handle node click - implement lazy loading with enhanced visual feedback\n */\n onNodeClick(event, d) {\n const clickId = Date.now() + Math.random();\n // DEBUG: Log all clicks to verify handler is working\n console.log(`🖱️🖱️🖱️ [NODE CLICK] onNodeClick method called! (ID: ${clickId}):`, {\n thisContext: this,\n isBound: this.constructor.name === 'CodeTree',\n name: d?.data?.name,\n path: d?.data?.path,\n type: d?.data?.type,\n loaded: d?.data?.loaded,\n hasChildren: !!(d?.children || d?._children),\n dataChildren: d?.data?.children?.length || 0,\n loadingNodesSize: this.loadingNodes ? this.loadingNodes.size : 'undefined'\n });\n\n // Update structured data with clicked node\n this.updateStructuredData(d);\n\n // Handle node click interaction\n \n // Check event parameter\n if (event) {\n try {\n if (typeof event.stopPropagation === 'function') {\n event.stopPropagation();\n } else {\n }\n } catch (error) {\n console.error('[CodeTree] ERROR calling stopPropagation:', error);\n }\n } else {\n }\n \n // Check d parameter structure\n if (!d) {\n console.error('[CodeTree] ERROR: d is null/undefined, cannot continue');\n return;\n }\n\n // Ignore clicks on root node - it should not be interactive\n if (d.data && (d.data.type === 'root' || d.data.isRoot || d.depth === 0)) {\n console.log('🚫 [ROOT CLICK] Ignoring click on root node:', d.data.name);\n return;\n }\n\n if (!d.data) {\n console.error('[CodeTree] ERROR: d.data is null/undefined, cannot continue');\n return;\n }\n \n // Node interaction detected\n \n // === PHASE 1: Immediate Visual Effects (Synchronous) ===\n // These execute immediately before any async operations\n \n \n // Center on clicked node (immediate visual effect) - REMOVED\n // Centering functionality has been disabled to prevent unwanted repositioning\n // when nodes are clicked. All other click functionality remains intact.\n // try {\n // if (this.isRadialLayout) {\n // if (typeof this.centerOnNodeRadial === 'function') {\n // this.centerOnNodeRadial(d);\n // } else {\n // console.error('[CodeTree] centerOnNodeRadial is not a function!');\n // }\n // } else {\n // if (typeof this.centerOnNode === 'function') {\n // this.centerOnNode(d);\n // } else {\n // console.error('[CodeTree] centerOnNode is not a function!');\n // }\n // }\n // } catch (error) {\n // console.error('[CodeTree] ERROR during centering:', error, error.stack);\n // }\n \n \n // Highlight with larger icon (immediate visual effect)\n try {\n if (typeof this.highlightActiveNode === 'function') {\n this.highlightActiveNode(d);\n } else {\n console.error('[CodeTree] highlightActiveNode is not a function!');\n }\n } catch (error) {\n console.error('[CodeTree] ERROR during highlightActiveNode:', error, error.stack);\n }\n \n \n // Show parent context (immediate visual effect)\n try {\n if (typeof this.showWithParent === 'function') {\n this.showWithParent(d);\n } else {\n console.error('[CodeTree] showWithParent is not a function!');\n }\n } catch (error) {\n console.error('[CodeTree] ERROR during showWithParent:', error, error.stack);\n }\n \n \n // Add pulsing animation immediately for directories\n \n if (this.isNodeDirectory(d) && !d.data.loaded) {\n try {\n if (typeof this.addLoadingPulse === 'function') {\n this.addLoadingPulse(d);\n } else {\n console.error('[CodeTree] addLoadingPulse is not a function!');\n }\n } catch (error) {\n console.error('[CodeTree] ERROR during addLoadingPulse:', error, error.stack);\n }\n } else {\n }\n \n \n // === PHASE 2: Prepare Data (Synchronous) ===\n \n \n // Get selected languages from checkboxes\n const selectedLanguages = this.getSelectedLanguages();\n console.log('🔍 [LANGUAGE] Selected languages:', selectedLanguages);\n \n // Get ignore patterns\n const ignorePatternsElement = document.getElementById('ignore-patterns');\n const ignorePatterns = ignorePatternsElement?.value || '';\n \n \n // === PHASE 3: Async Operations (Delayed) ===\n // Add a small delay to ensure visual effects are rendered first\n \n // For directories that haven't been loaded yet, request discovery\n console.log('🔍 [LOAD CHECK]', {\n type: d.data.type,\n loaded: d.data.loaded,\n loadedType: typeof d.data.loaded,\n isDirectory: d.data.type === 'directory' || d.data.type === 'root',\n notLoaded: !d.data.loaded,\n shouldLoad: (d.data.type === 'directory' || d.data.type === 'root') && !d.data.loaded\n });\n // Check for both 'directory' type and 'root' type (or use isDirectory flag)\n if ((d.data.type === 'directory' || d.data.type === 'root' || d.data.isDirectory) && !d.data.loaded) {\n console.log('✅ [SUBDIRECTORY LOADING] Load check passed, proceeding with loading logic');\n console.log('🔍 [SUBDIRECTORY LOADING] Initial loading state:', {\n loadingNodesSize: this.loadingNodes ? this.loadingNodes.size : 'undefined',\n loadingNodesContent: Array.from(this.loadingNodes || [])\n });\n\n try {\n // Debug the path and loadingNodes state\n console.log('🔍 [SUBDIRECTORY LOADING] Checking for duplicates:', {\n path: d.data.path,\n pathType: typeof d.data.path,\n loadingNodesType: typeof this.loadingNodes,\n loadingNodesSize: this.loadingNodes ? this.loadingNodes.size : 'undefined',\n hasMethod: this.loadingNodes && typeof this.loadingNodes.has === 'function'\n });\n\n // Prevent duplicate requests\n const isDuplicate = this.loadingNodes && this.loadingNodes.has(d.data.path);\n console.log('🔍 [SUBDIRECTORY LOADING] Duplicate check result:', {\n isDuplicate: isDuplicate,\n loadingNodesContent: Array.from(this.loadingNodes || []),\n pathBeingChecked: d.data.path\n });\n\n if (isDuplicate) {\n console.warn('⚠️ [SUBDIRECTORY LOADING] Duplicate request detected, but proceeding anyway:', {\n path: d.data.path,\n name: d.data.name,\n loadingNodesSize: this.loadingNodes.size,\n loadingNodesContent: Array.from(this.loadingNodes),\n pathInSet: this.loadingNodes.has(d.data.path)\n });\n // Remove the existing entry and proceed\n this.loadingNodes.delete(d.data.path);\n console.log('🧹 [SUBDIRECTORY LOADING] Removed duplicate entry, proceeding with fresh request');\n }\n\n console.log('✅ [SUBDIRECTORY LOADING] No duplicate request, proceeding to mark as loading');\n\n // Mark as loading immediately to prevent duplicate requests\n d.data.loaded = 'loading';\n this.loadingNodes.add(d.data.path);\n \n // Ensure path is absolute or relative to working directory\n const fullPath = this.ensureFullPath(d.data.path);\n \n // CRITICAL DEBUG: Log directory loading attempt\n console.log('🚀 [SUBDIRECTORY LOADING] Attempting to load:', {\n originalPath: d.data.path,\n fullPath: fullPath,\n nodeType: d.data.type,\n loaded: d.data.loaded,\n hasSocket: !!this.socket,\n workingDir: this.getWorkingDirectory()\n });\n \n // Sending discovery request for child content\n \n // Store reference to the D3 node for later expansion\n const clickedD3Node = d;\n \n // Delay the socket request to ensure visual effects are rendered\n // Use arrow function to preserve 'this' context\n setTimeout(() => {\n \n // CRITICAL FIX: Use REST API instead of WebSocket for reliability\n // The simple view works because it uses REST API, so let's do the same\n console.log('📡 [SUBDIRECTORY LOADING] Using REST API for directory:', {\n originalPath: d.data.path,\n fullPath: fullPath,\n apiUrl: `${window.location.origin}/api/directory?path=${encodeURIComponent(fullPath)}`,\n loadingNodesSize: this.loadingNodes.size,\n loadingNodesContent: Array.from(this.loadingNodes)\n });\n \n const apiUrl = `${window.location.origin}/api/directory?path=${encodeURIComponent(fullPath)}`;\n \n fetch(apiUrl)\n .then(response => {\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n return response.json();\n })\n .then(data => {\n console.log('✅ [SUBDIRECTORY LOADING] REST API response:', {\n data: data,\n pathToDelete: d.data.path,\n loadingNodesBefore: Array.from(this.loadingNodes)\n });\n \n // Remove from loading set\n const deleted = this.loadingNodes.delete(d.data.path);\n d.data.loaded = true;\n \n console.log('🧹 [SUBDIRECTORY LOADING] Cleanup result:', {\n pathDeleted: d.data.path,\n wasDeleted: deleted,\n loadingNodesAfter: Array.from(this.loadingNodes)\n });\n \n // Remove loading animation\n const d3Node = this.findD3NodeByPath(d.data.path);\n if (d3Node) {\n this.removeLoadingPulse(d3Node);\n }\n \n // Process the directory contents\n if (data.exists && data.is_directory && data.contents) {\n const node = this.findNodeByPath(d.data.path);\n if (node) {\n console.log('🔧 [SUBDIRECTORY LOADING] Creating children with paths:',\n data.contents.map(item => ({ name: item.name, path: item.path })));\n\n // Add children to the node\n node.children = data.contents.map(item => ({\n name: item.name,\n path: item.path, // Use the full path from API response\n type: item.is_directory ? 'directory' : 'file',\n loaded: item.is_directory ? false : undefined,\n analyzed: !item.is_directory ? false : undefined,\n expanded: false,\n children: item.is_directory ? [] : undefined\n }));\n node.loaded = true;\n node.expanded = true;\n \n // Update D3 hierarchy\n if (this.root && this.svg) {\n const oldRoot = this.root;\n this.root = d3.hierarchy(this.treeData);\n this.root.x0 = this.height / 2;\n this.root.y0 = 0;\n \n this.preserveExpansionState(oldRoot, this.root);\n \n const updatedD3Node = this.findD3NodeByPath(d.data.path);\n if (updatedD3Node && updatedD3Node.children && updatedD3Node.children.length > 0) {\n updatedD3Node._children = null;\n updatedD3Node.data.expanded = true;\n }\n \n this.update(updatedD3Node || this.root);\n\n // Focus on the newly loaded directory for better UX\n if (updatedD3Node && data.contents.length > 0) {\n setTimeout(() => {\n this.focusOnDirectory(updatedD3Node);\n }, 500); // Small delay to let the update animation complete\n }\n }\n\n this.updateBreadcrumb(`Loaded ${data.contents.length} items`, 'success');\n this.showNotification(`Loaded ${data.contents.length} items from ${d.data.name}`, 'success');\n }\n } else {\n this.showNotification(`Directory ${d.data.name} is empty or inaccessible`, 'warning');\n }\n })\n .catch(error => {\n console.error('❌ [SUBDIRECTORY LOADING] REST API error:', {\n error: error.message,\n stack: error.stack,\n pathToDelete: d.data.path,\n loadingNodesBefore: Array.from(this.loadingNodes)\n });\n \n // Clean up loading state\n const deleted = this.loadingNodes.delete(d.data.path);\n d.data.loaded = false;\n \n console.log('🧹 [SUBDIRECTORY LOADING] Error cleanup:', {\n pathDeleted: d.data.path,\n wasDeleted: deleted,\n loadingNodesAfter: Array.from(this.loadingNodes)\n });\n \n const d3Node = this.findD3NodeByPath(d.data.path);\n if (d3Node) {\n this.removeLoadingPulse(d3Node);\n }\n \n this.showNotification(`Failed to load ${d.data.name}: ${error.message}`, 'error');\n });\n \n this.updateBreadcrumb(`Loading ${d.data.name}...`, 'info');\n this.showNotification(`Loading directory: ${d.data.name}`, 'info');\n \n // Keep the original else clause for when fetch isn't available\n if (!window.fetch) {\n console.error('❌ [SUBDIRECTORY LOADING] No WebSocket connection available!');\n this.showNotification(`Cannot load directory: No connection`, 'error');\n \n // Clear loading state since the request failed\n this.loadingNodes.delete(d.data.path);\n const d3Node = this.findD3NodeByPath(d.data.path);\n if (d3Node) {\n this.removeLoadingPulse(d3Node);\n }\n // Reset the loaded flag\n d.data.loaded = false;\n }\n }, 100); // 100ms delay to ensure visual effects render first\n\n } catch (error) {\n console.error('❌ [SUBDIRECTORY LOADING] Error in directory loading logic:', {\n error: error.message,\n stack: error.stack,\n path: d.data.path,\n nodeData: d.data\n });\n this.showNotification(`Error loading directory: ${error.message}`, 'error');\n }\n }\n // For files, handle both content display and analysis\n else if (d.data.type === 'file') {\n console.log('📄 [FILE CLICK] File clicked:', {\n fileName: d.data.name,\n filePath: d.data.path,\n analyzed: d.data.analyzed\n });\n\n // PHASE 1: Display file content in unified data viewer\n this.displayFileInDataViewer(d);\n\n // PHASE 2: Handle AST analysis for code files (if not already analyzed)\n if (!d.data.analyzed) {\n // Only analyze files of selected languages\n const fileLanguage = this.detectLanguage(d.data.path);\n console.log('🔍 [FILE ANALYSIS] Language check:', {\n fileName: d.data.name,\n filePath: d.data.path,\n detectedLanguage: fileLanguage,\n selectedLanguages: selectedLanguages,\n isLanguageSelected: selectedLanguages.includes(fileLanguage),\n shouldAnalyze: selectedLanguages.includes(fileLanguage) || fileLanguage === 'unknown'\n });\n\n if (!selectedLanguages.includes(fileLanguage) && fileLanguage !== 'unknown') {\n console.warn('⚠️ [FILE ANALYSIS] Skipping AST analysis for file:', {\n fileName: d.data.name,\n detectedLanguage: fileLanguage,\n selectedLanguages: selectedLanguages,\n reason: `${fileLanguage} not in selected languages`\n });\n // Still show file content, just skip AST analysis\n return;\n }\n }\n \n // Add pulsing animation immediately\n this.addLoadingPulse(d);\n \n // Mark as loading immediately\n d.data.analyzed = 'loading';\n \n // Ensure path is absolute or relative to working directory\n const fullPath = this.ensureFullPath(d.data.path);\n \n // Delay the socket request to ensure visual effects are rendered\n setTimeout(() => {\n console.log('🚀 [FILE ANALYSIS] Sending analysis request:', {\n fileName: d.data.name,\n originalPath: d.data.path,\n fullPath: fullPath,\n hasSocket: !!this.socket,\n socketConnected: this.socket?.connected\n });\n\n if (this.socket && this.socket.connected) {\n console.log('📡 [FILE ANALYSIS] Using SocketIO for analysis:', {\n event: 'code:analyze:file',\n path: fullPath,\n socketConnected: this.socket.connected,\n socketId: this.socket.id\n });\n\n this.socket.emit('code:analyze:file', {\n path: fullPath\n });\n\n // Set a shorter timeout since we have a stable server\n const analysisTimeout = setTimeout(() => {\n console.warn('⏰ [FILE ANALYSIS] SocketIO timeout, trying HTTP fallback for:', fullPath);\n this.analyzeFileHTTP(fullPath, d.data.name, d3.select(event.target.closest('g')));\n }, 5000); // 5 second timeout\n\n // Store timeout ID for cleanup\n if (!this.analysisTimeouts) this.analysisTimeouts = new Map();\n this.analysisTimeouts.set(fullPath, analysisTimeout);\n\n this.updateBreadcrumb(`Analyzing ${d.data.name}...`, 'info');\n this.showNotification(`Analyzing: ${d.data.name}`, 'info');\n } else {\n console.log('🔄 [FILE ANALYSIS] SocketIO unavailable, using HTTP fallback');\n this.updateBreadcrumb(`Analyzing ${d.data.name}...`, 'info');\n this.showNotification(`Analyzing: ${d.data.name}`, 'info');\n this.analyzeFileHTTP(fullPath, d.data.name, d3.select(event.target.closest('g')));\n }\n }, 100); // 100ms delay to ensure visual effects render first\n }\n // Toggle children visibility for already loaded nodes\n else if (this.isNodeDirectory(d) && d.data.loaded === true) {\n // Directory is loaded, toggle expansion\n if (d.children) {\n // Collapse - hide children\n d._children = d.children;\n d.children = null;\n d.data.expanded = false;\n } else if (d._children) {\n // Expand - show children\n d.children = d._children;\n d._children = null;\n d.data.expanded = true;\n } else if (d.data.children && d.data.children.length > 0) {\n // Children exist in data but not in D3 node, recreate hierarchy\n this.root = d3.hierarchy(this.treeData);\n const updatedD3Node = this.findD3NodeByPath(d.data.path);\n if (updatedD3Node) {\n updatedD3Node.children = updatedD3Node._children || updatedD3Node.children;\n updatedD3Node._children = null;\n updatedD3Node.data.expanded = true;\n }\n }\n this.update(this.root);\n }\n // Also handle other nodes that might have children\n else if (d.children || d._children) {\n if (d.children) {\n d._children = d.children;\n d.children = null;\n d.data.expanded = false;\n } else {\n d.children = d._children;\n d._children = null;\n d.data.expanded = true;\n }\n this.update(d);\n } else {\n }\n \n // Update selection\n this.selectedNode = d;\n try {\n this.highlightNode(d);\n } catch (error) {\n console.error('[CodeTree] ERROR during highlightNode:', error);\n }\n \n }\n \n /**\n * Ensure path is absolute or relative to working directory\n */\n ensureFullPath(path) {\n console.log('🔗 ensureFullPath called with:', path);\n \n if (!path) return path;\n \n // If already absolute, return as is\n if (path.startsWith('/')) {\n console.log(' → Already absolute, returning:', path);\n return path;\n }\n \n // Get working directory\n const workingDir = this.getWorkingDirectory();\n console.log(' → Working directory:', workingDir);\n \n if (!workingDir) {\n console.log(' → No working directory, returning original:', path);\n return path;\n }\n \n // Special handling for root path\n if (path === '.') {\n console.log(' → Root path detected, returning working dir:', workingDir);\n return workingDir;\n }\n \n // If path equals working directory, return as is\n if (path === workingDir) {\n console.log(' → Path equals working directory, returning:', workingDir);\n return workingDir;\n }\n \n // Combine working directory with relative path\n const result = `${workingDir}/${path}`.replace(/\\/+/g, '/');\n console.log(' → Combining with working dir, result:', result);\n return result;\n }\n\n /**\n * Highlight selected node\n */\n highlightNode(node) {\n // Remove previous highlights\n this.treeGroup.selectAll('circle.node-circle')\n .style('stroke-width', 2)\n .classed('selected', false);\n\n // Highlight selected node\n this.treeGroup.selectAll('circle.node-circle')\n .filter(d => d === node)\n .style('stroke-width', 4)\n .classed('selected', true);\n }\n\n /**\n * Create diagonal path for links\n */\n diagonal(s, d) {\n return `M ${s.y} ${s.x}\n C ${(s.y + d.y) / 2} ${s.x},\n ${(s.y + d.y) / 2} ${d.x},\n ${d.y} ${d.x}`;\n }\n \n /**\n * Create radial diagonal path for links\n */\n radialDiagonal(s, d) {\n const path = d3.linkRadial()\n .angle(d => d.x)\n .radius(d => d.y);\n return path({source: s, target: d});\n }\n\n /**\n * Helper function to check if a node is a directory or root\n */\n isNodeDirectory(node) {\n const data = node.data || node;\n return data.type === 'directory' || data.type === 'root' || data.isDirectory === true;\n }\n \n /**\n * Get node color based on type and complexity\n */\n getNodeColor(d) {\n const type = d.data.type;\n const complexity = d.data.complexity || 1;\n\n // Base colors by type\n const baseColors = {\n 'root': '#6B7280',\n 'directory': '#3B82F6',\n 'file': '#10B981',\n 'module': '#8B5CF6',\n 'class': '#F59E0B',\n 'function': '#EF4444',\n 'method': '#EC4899'\n };\n\n const baseColor = baseColors[type] || '#6B7280';\n\n // Adjust brightness based on complexity (higher complexity = darker)\n if (complexity > 10) {\n return d3.color(baseColor).darker(0.5);\n } else if (complexity > 5) {\n return d3.color(baseColor).darker(0.25);\n }\n \n return baseColor;\n }\n\n /**\n * Get node stroke color\n */\n getNodeStrokeColor(d) {\n if (d.data.loaded === 'loading' || d.data.analyzed === 'loading') {\n return '#FCD34D'; // Yellow for loading\n }\n if (this.isNodeDirectory(d) && !d.data.loaded) {\n return '#94A3B8'; // Gray for unloaded\n }\n if (d.data.type === 'file' && !d.data.analyzed) {\n return '#CBD5E1'; // Light gray for unanalyzed\n }\n return this.getNodeColor(d);\n }\n\n /**\n * Get icon for node type\n */\n getNodeIcon(d) {\n const icons = {\n 'root': '📦',\n 'directory': '📁',\n 'file': '📄',\n 'module': '📦',\n 'class': 'C',\n 'function': 'ƒ',\n 'method': 'm'\n };\n return icons[d.data.type] || '•';\n }\n\n /**\n * Show tooltip on hover\n */\n showTooltip(event, d) {\n if (!this.tooltip) return;\n\n const info = [];\n info.push(`<strong>${d.data.name}</strong>`);\n info.push(`Type: ${d.data.type}`);\n \n if (d.data.language) {\n info.push(`Language: ${d.data.language}`);\n }\n if (d.data.complexity) {\n info.push(`Complexity: ${d.data.complexity}`);\n }\n if (d.data.lines) {\n info.push(`Lines: ${d.data.lines}`);\n }\n if (d.data.path) {\n info.push(`Path: ${d.data.path}`);\n }\n \n // Special messages for lazy-loaded nodes\n if (this.isNodeDirectory(d) && !d.data.loaded) {\n info.push('<em>Click to explore contents</em>');\n } else if (d.data.type === 'file' && !d.data.analyzed) {\n info.push('<em>Click to analyze file</em>');\n }\n\n this.tooltip.transition()\n .duration(200)\n .style('opacity', .9);\n\n this.tooltip.html(info.join('<br>'))\n .style('left', (event.pageX + 10) + 'px')\n .style('top', (event.pageY - 28) + 'px');\n }\n\n /**\n * Hide tooltip\n */\n hideTooltip() {\n if (!this.tooltip) return;\n \n this.tooltip.transition()\n .duration(500)\n .style('opacity', 0);\n }\n\n /**\n * Filter tree based on language and search\n */\n filterTree() {\n if (!this.root) return;\n\n // Apply filters\n this.root.descendants().forEach(d => {\n d.data._hidden = false;\n\n // Language filter\n if (this.languageFilter !== 'all') {\n if (d.data.type === 'file' && d.data.language !== this.languageFilter) {\n d.data._hidden = true;\n }\n }\n\n // Search filter\n if (this.searchTerm) {\n if (!d.data.name.toLowerCase().includes(this.searchTerm)) {\n d.data._hidden = true;\n }\n }\n });\n\n // Update display\n this.update(this.root);\n }\n\n /**\n * Expand all nodes in the tree\n */\n expandAll() {\n if (!this.root) return;\n \n // Recursively expand all nodes\n const expandRecursive = (node) => {\n if (node._children) {\n node.children = node._children;\n node._children = null;\n }\n if (node.children) {\n node.children.forEach(expandRecursive);\n }\n };\n \n expandRecursive(this.root);\n this.update(this.root);\n this.showNotification('All nodes expanded', 'info');\n }\n\n /**\n * Collapse all nodes in the tree\n */\n collapseAll() {\n if (!this.root) return;\n \n // Recursively collapse all nodes except root\n const collapseRecursive = (node) => {\n if (node.children) {\n node._children = node.children;\n node.children = null;\n }\n if (node._children) {\n node._children.forEach(collapseRecursive);\n }\n };\n \n this.root.children?.forEach(collapseRecursive);\n this.update(this.root);\n this.showNotification('All nodes collapsed', 'info');\n }\n\n /**\n * Focus on a specific directory, hiding parent directories and showing only its contents\n */\n focusOnDirectory(node) {\n if (!node || node.data.type !== 'directory') return;\n\n console.log('🎯 [FOCUS] Focusing on directory:', node.data.path);\n\n // Store the focused node\n this.focusedNode = node;\n\n // Create a temporary root for display purposes\n const focusedRoot = {\n ...node.data,\n name: `📁 ${node.data.name}`,\n children: node.data.children || []\n };\n\n // Create new D3 hierarchy with focused node as root\n const tempRoot = d3.hierarchy(focusedRoot);\n tempRoot.x0 = this.height / 2;\n tempRoot.y0 = 0;\n\n // Store original root for restoration\n if (!this.originalRoot) {\n this.originalRoot = this.root;\n }\n\n // Update with focused view\n this.root = tempRoot;\n this.update(this.root);\n\n // Add visual styling for focused mode\n d3.select('#code-tree-container').classed('focused', true);\n\n // Update breadcrumb to show focused path\n this.updateBreadcrumb(`Focused on: ${node.data.name}`, 'info');\n this.showNotification(`Focused on directory: ${node.data.name}`, 'info');\n\n // Add back button to toolbar\n this.addBackButton();\n }\n\n /**\n * Return to the full tree view from focused directory view\n */\n unfocusDirectory() {\n if (!this.originalRoot) return;\n\n console.log('🔙 [FOCUS] Returning to full tree view');\n\n // Restore original root\n this.root = this.originalRoot;\n this.originalRoot = null;\n this.focusedNode = null;\n\n // Update display\n this.update(this.root);\n\n // Remove visual styling for focused mode\n d3.select('#code-tree-container').classed('focused', false);\n\n // Remove back button\n this.removeBackButton();\n\n this.updateBreadcrumb('Full tree view restored', 'success');\n this.showNotification('Returned to full tree view', 'success');\n }\n\n /**\n * Add back button to return from focused view\n */\n addBackButton() {\n // Remove existing back button\n d3.select('#tree-back-button').remove();\n\n const toolbar = d3.select('.tree-controls-toolbar');\n if (toolbar.empty()) return;\n\n toolbar.insert('button', ':first-child')\n .attr('id', 'tree-back-button')\n .attr('class', 'tree-control-btn back-btn')\n .attr('title', 'Return to full tree view')\n .text('← Back')\n .on('click', () => this.unfocusDirectory());\n }\n\n /**\n * Remove back button\n */\n removeBackButton() {\n d3.select('#tree-back-button').remove();\n }\n\n /**\n * Reset zoom to fit the tree\n */\n resetZoom() {\n if (!this.svg || !this.zoom) return;\n\n // Calculate bounds of the tree\n const bounds = this.treeGroup.node().getBBox();\n const fullWidth = this.width;\n const fullHeight = this.height;\n const width = bounds.width;\n const height = bounds.height;\n const midX = bounds.x + width / 2;\n const midY = bounds.y + height / 2;\n\n if (width === 0 || height === 0) return; // Nothing to fit\n\n // Calculate scale to fit tree in view with some padding\n const scale = Math.min(fullWidth / width, fullHeight / height) * 0.9;\n\n // Calculate translate to center the tree\n const translate = [fullWidth / 2 - scale * midX, fullHeight / 2 - scale * midY];\n\n // Apply the transform with smooth transition\n this.svg.transition()\n .duration(750)\n .call(this.zoom.transform, d3.zoomIdentity.translate(translate[0], translate[1]).scale(scale));\n\n this.showNotification('Zoom reset to fit tree', 'info');\n }\n\n /**\n * Zoom in by a fixed factor\n */\n zoomIn() {\n if (!this.svg || !this.zoom) return;\n\n this.svg.transition()\n .duration(300)\n .call(this.zoom.scaleBy, 1.5);\n }\n\n /**\n * Zoom out by a fixed factor\n */\n zoomOut() {\n if (!this.svg || !this.zoom) return;\n\n this.svg.transition()\n .duration(300)\n .call(this.zoom.scaleBy, 1 / 1.5);\n }\n\n /**\n * Update zoom level display\n */\n updateZoomLevel(scale) {\n const zoomDisplay = document.getElementById('zoom-level-display');\n if (zoomDisplay) {\n zoomDisplay.textContent = `${Math.round(scale * 100)}%`;\n }\n }\n\n /**\n * Adjust text size to remain constant during zoom\n */\n adjustTextSizeForZoom(zoomScale) {\n if (!this.treeGroup) return;\n\n // Calculate the inverse scale to keep text at consistent size\n const textScale = 1 / zoomScale;\n\n // Apply inverse scaling to all text elements\n this.treeGroup.selectAll('text')\n .style('font-size', `${12 * textScale}px`)\n .attr('transform', function() {\n // Get existing transform if any\n const existingTransform = d3.select(this).attr('transform') || '';\n // Remove any existing scale transforms and add the new one\n const cleanTransform = existingTransform.replace(/scale\\([^)]*\\)/g, '').trim();\n return cleanTransform ? `${cleanTransform} scale(${textScale})` : `scale(${textScale})`;\n });\n\n // Also adjust other UI elements that should maintain size\n this.treeGroup.selectAll('.expand-icon')\n .style('font-size', `${12 * textScale}px`)\n .attr('transform', function() {\n const existingTransform = d3.select(this).attr('transform') || '';\n const cleanTransform = existingTransform.replace(/scale\\([^)]*\\)/g, '').trim();\n return cleanTransform ? `${cleanTransform} scale(${textScale})` : `scale(${textScale})`;\n });\n\n // Adjust item count badges\n this.treeGroup.selectAll('.item-count-badge')\n .style('font-size', `${10 * textScale}px`)\n .attr('transform', function() {\n const existingTransform = d3.select(this).attr('transform') || '';\n const cleanTransform = existingTransform.replace(/scale\\([^)]*\\)/g, '').trim();\n return cleanTransform ? `${cleanTransform} scale(${textScale})` : `scale(${textScale})`;\n });\n }\n\n /**\n * Add keyboard shortcuts for zoom functionality\n */\n addZoomKeyboardShortcuts() {\n // Only add shortcuts when the code tab is active\n document.addEventListener('keydown', (event) => {\n // Check if code tab is active\n const codeTab = document.getElementById('code-tab');\n if (!codeTab || !codeTab.classList.contains('active')) {\n return;\n }\n\n // Prevent shortcuts when typing in input fields\n if (event.target.tagName === 'INPUT' || event.target.tagName === 'TEXTAREA') {\n return;\n }\n\n // Handle zoom shortcuts\n if (event.ctrlKey || event.metaKey) {\n switch (event.key) {\n case '=':\n case '+':\n event.preventDefault();\n this.zoomIn();\n break;\n case '-':\n event.preventDefault();\n this.zoomOut();\n break;\n case '0':\n event.preventDefault();\n this.resetZoom();\n break;\n }\n }\n });\n }\n\n /**\n * Check if a file path represents a source file that should show source viewer\n */\n isSourceFile(path) {\n if (!path) return false;\n const sourceExtensions = ['.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.cpp', '.c', '.h', '.cs', '.php', '.rb', '.go', '.rs', '.swift'];\n return sourceExtensions.some(ext => path.toLowerCase().endsWith(ext));\n }\n\n /**\n * Show hierarchical source viewer for a source file\n */\n async showSourceViewer(node) {\n console.log('📄 [SOURCE VIEWER] Starting showSourceViewer for:', node.data.path);\n console.log(' Node type:', node.data.type);\n console.log(' Content element available:', !!this.structuredDataContent);\n \n if (!this.structuredDataContent) {\n console.error('❌ [SOURCE VIEWER] No content element to display source in!');\n return;\n }\n\n // Create source viewer container\n const sourceViewer = document.createElement('div');\n sourceViewer.className = 'source-viewer';\n console.log('📦 [SOURCE VIEWER] Created source viewer container');\n\n // Create header\n const header = document.createElement('div');\n header.className = 'source-viewer-header';\n header.innerHTML = `\n <span>📄 ${node.data.name || 'Source File'}</span>\n <div class=\"source-viewer-controls\">\n <button class=\"source-control-btn\" id=\"expand-all-source\" title=\"Expand all\">⬇</button>\n <button class=\"source-control-btn\" id=\"collapse-all-source\" title=\"Collapse all\">⬆</button>\n </div>\n `;\n\n // Create content container\n const content = document.createElement('div');\n content.className = 'source-viewer-content';\n content.id = 'source-viewer-content';\n\n sourceViewer.appendChild(header);\n sourceViewer.appendChild(content);\n console.log('🔨 [SOURCE VIEWER] Appending source viewer to content element...');\n this.structuredDataContent.appendChild(sourceViewer);\n console.log('✅ [SOURCE VIEWER] Source viewer added to DOM');\n console.log(' Content element children count:', this.structuredDataContent.children.length);\n console.log(' Content element HTML preview:', this.structuredDataContent.innerHTML.substring(0, 200) + '...');\n\n // Add control event listeners\n document.getElementById('expand-all-source')?.addEventListener('click', () => this.expandAllSource());\n document.getElementById('collapse-all-source')?.addEventListener('click', () => this.collapseAllSource());\n\n // Load and display source code\n try {\n await this.loadSourceContent(node, content);\n } catch (error) {\n console.error('Failed to load source content:', error);\n content.innerHTML = `\n <div class=\"ast-data-placeholder\">\n <div class=\"ast-placeholder-icon\">❌</div>\n <div class=\"ast-placeholder-text\">Failed to load source file</div>\n </div>\n `;\n }\n }\n\n /**\n * REMOVED: Focus on a specific node and its subtree\n * This method has been completely disabled to prevent unwanted tree movement.\n * All centering and focus functionality has been removed from the code tree.\n */\n focusOnNode(node) {\n // Method disabled - no focusing/centering operations will be performed\n console.log('[CodeTree] focusOnNode called but disabled - no focusing will occur');\n return;\n \n // Update breadcrumb with focused path\n const path = this.getNodePath(node);\n this.updateBreadcrumb(`Focused: ${path}`, 'info');\n }\n \n /**\n * Get the full path of a node\n */\n getNodePath(node) {\n const path = [];\n let current = node;\n while (current) {\n if (current.data && current.data.name) {\n path.unshift(current.data.name);\n }\n current = current.parent;\n }\n return path.join(' / ');\n }\n\n /**\n * Toggle legend visibility\n */\n toggleLegend() {\n const legend = document.getElementById('tree-legend');\n if (legend) {\n if (legend.style.display === 'none') {\n legend.style.display = 'block';\n } else {\n legend.style.display = 'none';\n }\n }\n }\n\n /**\n * Get the current working directory\n */\n getWorkingDirectory() {\n // Try to get from dashboard's working directory manager\n if (window.dashboard && window.dashboard.workingDirectoryManager) {\n return window.dashboard.workingDirectoryManager.getCurrentWorkingDir();\n }\n \n // Fallback to checking the DOM element\n const workingDirPath = document.getElementById('working-dir-path');\n if (workingDirPath) {\n const pathText = workingDirPath.textContent.trim();\n if (pathText && pathText !== 'Loading...' && pathText !== 'Not selected') {\n return pathText;\n }\n }\n \n return null;\n }\n \n /**\n * Show a message when no working directory is selected\n */\n showNoWorkingDirectoryMessage() {\n const container = document.getElementById('code-tree-container');\n if (!container) return;\n \n // Remove any existing message\n this.removeNoWorkingDirectoryMessage();\n \n // Hide loading if shown\n this.hideLoading();\n \n // Create message element\n const messageDiv = document.createElement('div');\n messageDiv.id = 'no-working-dir-message';\n messageDiv.className = 'no-working-dir-message';\n messageDiv.innerHTML = `\n <div class=\"message-icon\">📁</div>\n <h3>No Working Directory Selected</h3>\n <p>Please select a working directory from the top menu to analyze code.</p>\n <button id=\"select-working-dir-btn\" class=\"btn btn-primary\">\n Select Working Directory\n </button>\n `;\n messageDiv.style.cssText = `\n text-align: center;\n padding: 40px;\n color: #666;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n `;\n \n // Style the message elements\n const messageIcon = messageDiv.querySelector('.message-icon');\n if (messageIcon) {\n messageIcon.style.cssText = 'font-size: 48px; margin-bottom: 16px; opacity: 0.5;';\n }\n \n const h3 = messageDiv.querySelector('h3');\n if (h3) {\n h3.style.cssText = 'margin: 16px 0; color: #333; font-size: 20px;';\n }\n \n const p = messageDiv.querySelector('p');\n if (p) {\n p.style.cssText = 'margin: 16px 0; color: #666; font-size: 14px;';\n }\n \n const button = messageDiv.querySelector('button');\n if (button) {\n button.style.cssText = `\n margin-top: 20px;\n padding: 10px 20px;\n background: #3b82f6;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n transition: background 0.2s;\n `;\n button.addEventListener('mouseenter', () => {\n button.style.background = '#2563eb';\n });\n button.addEventListener('mouseleave', () => {\n button.style.background = '#3b82f6';\n });\n button.addEventListener('click', () => {\n // Trigger working directory selection\n const changeDirBtn = document.getElementById('change-dir-btn');\n if (changeDirBtn) {\n changeDirBtn.click();\n } else if (window.dashboard && window.dashboard.workingDirectoryManager) {\n window.dashboard.workingDirectoryManager.showChangeDirDialog();\n }\n });\n }\n \n container.appendChild(messageDiv);\n \n // Update breadcrumb\n this.updateBreadcrumb('Please select a working directory', 'warning');\n }\n \n /**\n * Remove the no working directory message\n */\n removeNoWorkingDirectoryMessage() {\n const message = document.getElementById('no-working-dir-message');\n if (message) {\n message.remove();\n }\n }\n \n /**\n * Debug function to clear loading state (for troubleshooting)\n */\n clearLoadingState() {\n console.log('🧹 [DEBUG] Clearing loading state:', {\n loadingNodesBefore: Array.from(this.loadingNodes),\n size: this.loadingNodes.size\n });\n this.loadingNodes.clear();\n\n // Also reset any nodes marked as 'loading'\n this.resetLoadingFlags(this.treeData);\n\n console.log('✅ [DEBUG] Loading state cleared');\n this.showNotification('Loading state cleared', 'info');\n }\n\n /**\n * Recursively reset loading flags in tree data\n */\n resetLoadingFlags(node) {\n if (node.loaded === 'loading') {\n node.loaded = false;\n }\n if (node.children) {\n node.children.forEach(child => this.resetLoadingFlags(child));\n }\n }\n\n /**\n * Export tree data\n */\n exportTree() {\n const exportData = {\n timestamp: new Date().toISOString(),\n workingDirectory: this.getWorkingDirectory(),\n stats: this.stats,\n tree: this.treeData\n };\n\n const blob = new Blob([JSON.stringify(exportData, null, 2)], \n {type: 'application/json'});\n const url = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = url;\n link.download = `code-tree-${Date.now()}.json`;\n link.click();\n URL.revokeObjectURL(url);\n\n this.showNotification('Tree exported successfully', 'success');\n }\n\n /**\n * Update activity ticker with real-time messages\n */\n updateActivityTicker(message, type = 'info') {\n const breadcrumb = document.getElementById('breadcrumb-content');\n if (breadcrumb) {\n // Add spinning icon for loading states\n const icon = type === 'info' && message.includes('...') ? '⟳ ' : '';\n breadcrumb.innerHTML = `${icon}${message}`;\n breadcrumb.className = `breadcrumb-${type}`;\n }\n }\n \n /**\n * Update ticker message\n */\n updateTicker(message, type = 'info') {\n const ticker = document.getElementById('code-tree-ticker');\n if (ticker) {\n ticker.textContent = message;\n ticker.className = `ticker ticker-${type}`;\n\n // Auto-hide after 5 seconds for non-error messages\n if (type !== 'error') {\n setTimeout(() => {\n ticker.style.opacity = '0';\n setTimeout(() => {\n ticker.style.opacity = '1';\n ticker.textContent = '';\n }, 300);\n }, 5000);\n }\n }\n }\n\n /**\n * Initialize the structured data integration\n */\n initializeStructuredData() {\n console.log('🔄 [CODE TREE] Initializing structured data integration...');\n \n // Use the existing \"📊 Structured Data\" section in the left panel\n this.structuredDataContent = document.getElementById('module-data-content');\n\n if (!this.structuredDataContent) {\n console.warn('⏳ [CODE TREE] Structured data element not found yet, retrying in 500ms...');\n \n // Retry after a short delay in case DOM is still loading\n setTimeout(() => {\n this.structuredDataContent = document.getElementById('module-data-content');\n \n if (!this.structuredDataContent) {\n console.error('❌ [CODE TREE] Structured data content element (#module-data-content) not found after retry!');\n console.log('[CODE TREE] Checking DOM for available elements...');\n // Debug: List all elements with module or data in their ID\n const allElements = document.querySelectorAll('[id*=\"module\"], [id*=\"data\"]');\n console.log(`[CODE TREE] Found ${allElements.length} elements with \"module\" or \"data\" in ID:`);\n allElements.forEach(el => {\n console.log(` - #${el.id} (class: ${el.className}, parent: ${el.parentElement?.id || 'no-parent'})`);\n });\n \n // Also check for the module viewer container\n const moduleViewer = document.querySelector('.module-viewer');\n if (moduleViewer) {\n console.log('[CODE TREE] Module viewer found, checking children...');\n const moduleDataContent = moduleViewer.querySelector('#module-data-content');\n if (moduleDataContent) {\n console.log('[CODE TREE] Found module-data-content via query selector!');\n this.structuredDataContent = moduleDataContent;\n } else {\n console.log('[CODE TREE] Module data content not found in module viewer');\n }\n }\n } else {\n console.log('✅ [CODE TREE] Structured data integration initialized on retry');\n console.log(' Target element:', this.structuredDataContent);\n console.log(' Parent element:', this.structuredDataContent.parentElement);\n }\n }, 500);\n return;\n }\n\n console.log('✅ [CODE TREE] Structured data integration initialized immediately');\n console.log(' Target element:', this.structuredDataContent);\n console.log(' Parent element:', this.structuredDataContent.parentElement);\n }\n\n /**\n * Update structured data with node information\n */\n updateStructuredData(node) {\n console.log('📝 [STRUCTURED DATA] updateStructuredData called');\n \n if (!this.structuredDataContent) {\n console.warn('⚠️ [STRUCTURED DATA] Content element not available, trying to find it...');\n // Try to find it again in case it wasn't initialized properly\n this.structuredDataContent = document.getElementById('module-data-content');\n \n if (!this.structuredDataContent) {\n console.error('❌ [STRUCTURED DATA] Cannot find module-data-content element!');\n // Last resort - try to find it in module viewer\n const moduleViewer = document.querySelector('.module-viewer');\n if (moduleViewer) {\n this.structuredDataContent = moduleViewer.querySelector('#module-data-content');\n if (this.structuredDataContent) {\n console.log('✅ [STRUCTURED DATA] Found element via module-viewer query');\n } else {\n console.error('❌ [STRUCTURED DATA] Still cannot find element, aborting update');\n return;\n }\n } else {\n console.error('❌ [STRUCTURED DATA] Module viewer not found either, aborting update');\n return;\n }\n } else {\n console.log('✅ [STRUCTURED DATA] Found element on retry');\n }\n }\n\n console.log('🔍 [STRUCTURED DATA] Updating with node:', {\n name: node?.data?.name,\n type: node?.data?.type,\n path: node?.data?.path,\n hasChildren: !!(node?.children || node?._children),\n dataChildren: node?.data?.children?.length || 0,\n contentElement: this.structuredDataContent\n });\n\n // Clear previous content\n this.structuredDataContent.innerHTML = '';\n console.log('🧹 [STRUCTURED DATA] Cleared previous content');\n\n // Check if this is a source file that should show source viewer\n if (node.data.type === 'file' && this.isSourceFile(node.data.path)) {\n this.showSourceViewer(node);\n } else {\n // Show children or functions for non-source files\n const children = node.children || node._children || [];\n const dataChildren = node.data.children || [];\n\n if (children.length > 0 || dataChildren.length > 0) {\n this.showASTNodeChildren(node);\n } else if (node.data.type === 'file' && node.data.analyzed) {\n this.showASTFileDetails(node);\n } else {\n this.showASTNodeDetails(node);\n }\n }\n }\n\n /**\n * Show child nodes in structured data\n */\n showASTNodeChildren(node) {\n const children = node.children || node._children || [];\n const dataChildren = node.data.children || [];\n\n // Use D3 children if available, otherwise use data children\n const childrenToShow = children.length > 0 ? children : dataChildren;\n\n if (childrenToShow.length === 0) {\n this.showASTEmptyState('No children found');\n return;\n }\n\n // Create header\n const header = document.createElement('div');\n header.className = 'structured-view-header';\n header.innerHTML = `<h4>${this.getNodeIcon(node.data.type)} ${node.data.name || 'Node'} - Children (${childrenToShow.length})</h4>`;\n this.structuredDataContent.appendChild(header);\n\n childrenToShow.forEach((child, index) => {\n const childData = child.data || child;\n const item = this.createASTDataViewerItem(childData, index);\n this.structuredDataContent.appendChild(item);\n });\n }\n\n /**\n * Show file details in structured data\n */\n showASTFileDetails(node) {\n // Create header\n const header = document.createElement('div');\n header.className = 'structured-view-header';\n header.innerHTML = `<h4>${this.getNodeIcon(node.data.type)} ${node.data.name || 'File'} - Details</h4>`;\n this.structuredDataContent.appendChild(header);\n\n const details = [];\n\n if (node.data.language) {\n details.push({ label: 'Language', value: node.data.language });\n }\n\n if (node.data.lines) {\n details.push({ label: 'Lines', value: node.data.lines });\n }\n\n if (node.data.complexity !== undefined) {\n details.push({ label: 'Complexity', value: node.data.complexity });\n }\n\n if (node.data.size) {\n details.push({ label: 'Size', value: this.formatFileSize(node.data.size) });\n }\n\n if (details.length === 0) {\n this.showASTEmptyState('No details available');\n return;\n }\n\n details.forEach((detail, index) => {\n const item = this.createASTDetailItem(detail, index);\n this.structuredDataContent.appendChild(item);\n });\n }\n\n /**\n * Show basic node details in structured data\n */\n showASTNodeDetails(node) {\n // Create header\n const header = document.createElement('div');\n header.className = 'structured-view-header';\n header.innerHTML = `<h4>${this.getNodeIcon(node.data.type)} ${node.data.name || 'Node'} - Details</h4>`;\n this.structuredDataContent.appendChild(header);\n\n const details = [];\n\n details.push({ label: 'Type', value: node.data.type || 'unknown' });\n details.push({ label: 'Path', value: node.data.path || 'unknown' });\n\n if (node.data.line) {\n details.push({ label: 'Line', value: node.data.line });\n }\n\n details.forEach((detail, index) => {\n const item = this.createASTDetailItem(detail, index);\n this.structuredDataContent.appendChild(item);\n });\n }\n\n /**\n * Create an AST data viewer item for a child node\n */\n createASTDataViewerItem(childData, index) {\n const item = document.createElement('div');\n item.className = 'ast-data-viewer-item';\n item.dataset.index = index;\n\n const header = document.createElement('div');\n header.className = 'ast-data-item-header';\n\n const name = document.createElement('div');\n name.className = 'ast-data-item-name';\n name.innerHTML = `${this.getNodeIcon(childData.type)} ${childData.name || 'Unknown'}`;\n\n const type = document.createElement('div');\n type.className = `ast-data-item-type ${childData.type || 'unknown'}`;\n type.textContent = childData.type || 'unknown';\n\n header.appendChild(name);\n header.appendChild(type);\n\n const details = document.createElement('div');\n details.className = 'ast-data-item-details';\n\n const detailParts = [];\n\n if (childData.line) {\n detailParts.push(`<span class=\"ast-data-item-line\">Line ${childData.line}</span>`);\n }\n\n if (childData.complexity !== undefined) {\n const complexityLevel = this.getComplexityLevel(childData.complexity);\n detailParts.push(`<span class=\"ast-data-item-complexity\">\n <span class=\"ast-complexity-indicator ${complexityLevel}\"></span>\n Complexity: ${childData.complexity}\n </span>`);\n }\n\n if (childData.docstring) {\n detailParts.push(`<div style=\"margin-top: 4px; font-style: italic;\">${childData.docstring}</div>`);\n }\n\n details.innerHTML = detailParts.join(' ');\n\n item.appendChild(header);\n item.appendChild(details);\n\n // Add click handler to select item\n item.addEventListener('click', () => {\n this.selectASTDataViewerItem(item);\n });\n\n return item;\n }\n\n /**\n * Create a detail item for simple key-value pairs\n */\n createASTDetailItem(detail, index) {\n const item = document.createElement('div');\n item.className = 'ast-data-viewer-item';\n item.dataset.index = index;\n\n const header = document.createElement('div');\n header.className = 'ast-data-item-header';\n\n const name = document.createElement('div');\n name.className = 'ast-data-item-name';\n name.textContent = detail.label;\n\n const value = document.createElement('div');\n value.className = 'ast-data-item-details';\n value.textContent = detail.value;\n\n header.appendChild(name);\n item.appendChild(header);\n item.appendChild(value);\n\n return item;\n }\n\n /**\n * Show empty state in structured data\n */\n showASTEmptyState(message) {\n this.structuredDataContent.innerHTML = `\n <div class=\"ast-data-placeholder\">\n <div class=\"ast-placeholder-icon\">📭</div>\n <div class=\"ast-placeholder-text\">${message}</div>\n </div>\n `;\n }\n\n /**\n * Select an AST data viewer item\n */\n selectASTDataViewerItem(item) {\n // Remove previous selection\n const previousSelected = this.structuredDataContent.querySelector('.ast-data-viewer-item.selected');\n if (previousSelected) {\n previousSelected.classList.remove('selected');\n }\n\n // Select new item\n item.classList.add('selected');\n this.selectedASTItem = item;\n }\n\n /**\n * Get icon for node type\n */\n getNodeIcon(type) {\n const icons = {\n 'directory': '📁',\n 'file': '📄',\n 'class': '🏛️',\n 'function': '⚡',\n 'method': '🔧',\n 'variable': '📦',\n 'import': '📥',\n 'module': '📦'\n };\n return icons[type] || '📄';\n }\n\n /**\n * Get complexity level for styling\n */\n getComplexityLevel(complexity) {\n if (complexity <= 5) return 'low';\n if (complexity <= 10) return 'medium';\n return 'high';\n }\n\n /**\n * Format file size for display\n */\n formatFileSize(bytes) {\n if (bytes === 0) return '0 B';\n const k = 1024;\n const sizes = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n }\n\n /**\n * Load source content and render with AST integration\n */\n async loadSourceContent(node, contentContainer) {\n // Try to read the file content\n const sourceContent = await this.readSourceFile(node.data.path);\n if (!sourceContent) {\n throw new Error('Could not read source file');\n }\n\n // Get AST elements for this file\n const astElements = node.data.children || [];\n\n // Parse and render source with AST integration\n this.renderSourceWithAST(sourceContent, astElements, contentContainer, node);\n }\n\n /**\n * Read source file content\n */\n async readSourceFile(filePath) {\n try {\n console.log('📖 [SOURCE READER] Reading file:', filePath);\n \n // Make API call to read the actual file content\n const response = await fetch(`/api/file/read?path=${encodeURIComponent(filePath)}`);\n \n if (!response.ok) {\n const error = await response.json();\n console.error('Failed to read file:', error);\n // Fall back to placeholder for errors\n return this.generatePlaceholderSource(filePath);\n }\n \n const data = await response.json();\n console.log('📖 [SOURCE READER] Read', data.lines, 'lines from', data.name);\n return data.content;\n \n } catch (error) {\n console.error('Failed to read source file:', error);\n // Fall back to placeholder on error\n return this.generatePlaceholderSource(filePath);\n }\n }\n\n /**\n * Generate placeholder source content for demonstration\n */\n generatePlaceholderSource(filePath) {\n const fileName = filePath.split('/').pop();\n\n if (fileName.endsWith('.py')) {\n return `\"\"\"\n${fileName}\nGenerated placeholder content for demonstration\n\"\"\"\n\nimport os\nimport sys\nfrom typing import List, Dict, Optional\n\nclass ExampleClass:\n \"\"\"Example class with methods.\"\"\"\n\n def __init__(self, name: str):\n \"\"\"Initialize the example class.\"\"\"\n self.name = name\n self.data = {}\n\n def process_data(self, items: List[str]) -> Dict[str, int]:\n \"\"\"Process a list of items and return counts.\"\"\"\n result = {}\n for item in items:\n result[item] = result.get(item, 0) + 1\n return result\n\n def get_summary(self) -> str:\n \"\"\"Get a summary of the processed data.\"\"\"\n if not self.data:\n return \"No data processed\"\n return f\"Processed {len(self.data)} items\"\n\ndef main():\n \"\"\"Main function.\"\"\"\n example = ExampleClass(\"demo\")\n items = [\"a\", \"b\", \"a\", \"c\", \"b\", \"a\"]\n result = example.process_data(items)\n print(example.get_summary())\n return result\n\nif __name__ == \"__main__\":\n main()\n`;\n } else {\n return `// ${fileName}\n// Generated placeholder content for demonstration\n\nclass ExampleClass {\n constructor(name) {\n this.name = name;\n this.data = {};\n }\n\n processData(items) {\n const result = {};\n for (const item of items) {\n result[item] = (result[item] || 0) + 1;\n }\n return result;\n }\n\n getSummary() {\n if (Object.keys(this.data).length === 0) {\n return \"No data processed\";\n }\n return \\`Processed \\${Object.keys(this.data).length} items\\`;\n }\n}\n\nfunction main() {\n const example = new ExampleClass(\"demo\");\n const items = [\"a\", \"b\", \"a\", \"c\", \"b\", \"a\"];\n const result = example.processData(items);\n console.log(example.getSummary());\n return result;\n}\n\nmain();\n`;\n }\n }\n\n /**\n * Render source code with AST integration and collapsible sections\n */\n renderSourceWithAST(sourceContent, astElements, container, node) {\n const lines = sourceContent.split('\\n');\n const astMap = this.createASTLineMap(astElements);\n\n console.log('🎨 [SOURCE RENDERER] Rendering source with AST:', {\n lines: lines.length,\n astElements: astElements.length,\n astMap: Object.keys(astMap).length\n });\n\n // Create line elements with AST integration\n lines.forEach((line, index) => {\n const lineNumber = index + 1;\n const lineElement = this.createSourceLine(line, lineNumber, astMap[lineNumber], node);\n container.appendChild(lineElement);\n });\n\n // Store reference for expand/collapse operations\n this.currentSourceContainer = container;\n this.currentASTElements = astElements;\n }\n\n /**\n * Create AST line mapping for quick lookup\n */\n createASTLineMap(astElements) {\n const lineMap = {};\n\n astElements.forEach(element => {\n if (element.line) {\n if (!lineMap[element.line]) {\n lineMap[element.line] = [];\n }\n lineMap[element.line].push(element);\n }\n });\n\n return lineMap;\n }\n\n /**\n * Create a source line element with AST integration\n */\n createSourceLine(content, lineNumber, astElements, node) {\n const lineDiv = document.createElement('div');\n lineDiv.className = 'source-line';\n lineDiv.dataset.lineNumber = lineNumber;\n\n // Check if this line has AST elements\n const hasAST = astElements && astElements.length > 0;\n if (hasAST) {\n lineDiv.classList.add('ast-element');\n lineDiv.dataset.astElements = JSON.stringify(astElements);\n }\n\n // Determine if this line should be collapsible\n const isCollapsible = this.isCollapsibleLine(content, astElements);\n if (isCollapsible) {\n lineDiv.classList.add('collapsible');\n }\n\n // Create line number\n const lineNumberSpan = document.createElement('span');\n lineNumberSpan.className = 'line-number';\n lineNumberSpan.textContent = lineNumber;\n\n // Create collapse indicator\n const collapseIndicator = document.createElement('span');\n collapseIndicator.className = 'collapse-indicator';\n if (isCollapsible) {\n collapseIndicator.classList.add('expanded');\n collapseIndicator.addEventListener('click', (e) => {\n e.stopPropagation();\n this.toggleSourceSection(lineDiv);\n });\n } else {\n collapseIndicator.classList.add('none');\n }\n\n // Create line content with syntax highlighting\n const lineContentSpan = document.createElement('span');\n lineContentSpan.className = 'line-content';\n lineContentSpan.innerHTML = this.applySyntaxHighlighting(content);\n\n // Add click handler for AST integration\n if (hasAST) {\n lineDiv.addEventListener('click', () => {\n this.onSourceLineClick(lineDiv, astElements, node);\n });\n }\n\n lineDiv.appendChild(lineNumberSpan);\n lineDiv.appendChild(collapseIndicator);\n lineDiv.appendChild(lineContentSpan);\n\n return lineDiv;\n }\n\n /**\n * Check if a line should be collapsible (function/class definitions)\n */\n isCollapsibleLine(content, astElements) {\n const trimmed = content.trim();\n\n // Python patterns\n if (trimmed.startsWith('def ') || trimmed.startsWith('class ') ||\n trimmed.startsWith('async def ')) {\n return true;\n }\n\n // JavaScript patterns\n if (trimmed.includes('function ') || trimmed.includes('class ') ||\n trimmed.includes('=> {') || trimmed.match(/^\\s*\\w+\\s*\\([^)]*\\)\\s*{/)) {\n return true;\n }\n\n // Check AST elements for function/class definitions\n if (astElements) {\n return astElements.some(el =>\n el.type === 'function' || el.type === 'class' ||\n el.type === 'method' || el.type === 'FunctionDef' ||\n el.type === 'ClassDef'\n );\n }\n\n return false;\n }\n\n /**\n * Apply basic syntax highlighting\n */\n applySyntaxHighlighting(content, fileType = 'text') {\n // First, properly escape HTML entities\n let highlighted = content\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n\n // Store markers for where we'll insert spans\n const replacements = [];\n \n // Check if this is JSON content\n const isJson = fileType === 'json' || this.currentFilePath?.endsWith('.json');\n \n if (isJson) {\n // JSON-specific highlighting\n // JSON property names (keys)\n const jsonKeys = /\"([^\"]+)\"(?=\\s*:)/g;\n let match;\n while ((match = jsonKeys.exec(highlighted)) !== null) {\n replacements.push({\n start: match.index,\n end: match.index + match[0].length,\n replacement: `<span class=\"json-key\">${match[0]}</span>`\n });\n }\n \n // JSON strings (values)\n const jsonStrings = /:\\s*\"([^\"]*)\"/g;\n while ((match = jsonStrings.exec(highlighted)) !== null) {\n const colonIndex = match[0].indexOf('\"');\n replacements.push({\n start: match.index + colonIndex,\n end: match.index + match[0].length,\n replacement: `<span class=\"string\">\"${match[1]}\"</span>`\n });\n }\n \n // JSON numbers\n const jsonNumbers = /:\\s*(-?\\d+\\.?\\d*)/g;\n while ((match = jsonNumbers.exec(highlighted)) !== null) {\n const numberStart = match[0].indexOf(match[1]);\n replacements.push({\n start: match.index + numberStart,\n end: match.index + match[0].length,\n replacement: `<span class=\"number\">${match[1]}</span>`\n });\n }\n \n // JSON booleans and null\n const jsonLiterals = /\\b(true|false|null)\\b/g;\n while ((match = jsonLiterals.exec(highlighted)) !== null) {\n replacements.push({\n start: match.index,\n end: match.index + match[0].length,\n replacement: `<span class=\"literal\">${match[0]}</span>`\n });\n }\n } else {\n // Python and JavaScript keywords (combined)\n const keywords = /\\b(def|class|import|from|if|else|elif|for|while|try|except|finally|with|as|return|yield|lambda|async|await|function|const|let|var|catch|export)\\b/g;\n \n // Find all matches first without replacing\n let match;\n \n // Keywords\n while ((match = keywords.exec(highlighted)) !== null) {\n replacements.push({\n start: match.index,\n end: match.index + match[0].length,\n replacement: `<span class=\"keyword\">${match[0]}</span>`\n });\n }\n \n // Strings - simple pattern for now\n const stringPattern = /([\"'`])([^\"'`]*?)\\1/g;\n while ((match = stringPattern.exec(highlighted)) !== null) {\n replacements.push({\n start: match.index,\n end: match.index + match[0].length,\n replacement: `<span class=\"string\">${match[0]}</span>`\n });\n }\n \n // Comments\n const commentPattern = /(#.*$|\\/\\/.*$)/gm;\n while ((match = commentPattern.exec(highlighted)) !== null) {\n replacements.push({\n start: match.index,\n end: match.index + match[0].length,\n replacement: `<span class=\"comment\">${match[0]}</span>`\n });\n }\n }\n \n // Sort replacements by start position (reverse order to not mess up indices)\n replacements.sort((a, b) => b.start - a.start);\n \n // Apply replacements\n for (const rep of replacements) {\n // Check for overlapping replacements and skip if needed\n const before = highlighted.substring(0, rep.start);\n const after = highlighted.substring(rep.end);\n \n // Only apply if we're not inside another replacement\n if (!before.includes('<span') || before.lastIndexOf('</span>') > before.lastIndexOf('<span')) {\n highlighted = before + rep.replacement + after;\n }\n }\n \n return highlighted;\n }\n\n /**\n * Toggle collapse/expand of a source section\n */\n toggleSourceSection(lineElement) {\n const indicator = lineElement.querySelector('.collapse-indicator');\n const isExpanded = indicator.classList.contains('expanded');\n\n if (isExpanded) {\n this.collapseSourceSection(lineElement);\n } else {\n this.expandSourceSection(lineElement);\n }\n }\n\n /**\n * Collapse a source section\n */\n collapseSourceSection(lineElement) {\n const indicator = lineElement.querySelector('.collapse-indicator');\n indicator.classList.remove('expanded');\n indicator.classList.add('collapsed');\n\n // Find and hide related lines (simple implementation)\n const startLine = parseInt(lineElement.dataset.lineNumber);\n const container = lineElement.parentElement;\n const lines = Array.from(container.children);\n\n // Hide subsequent indented lines\n let currentIndex = lines.indexOf(lineElement) + 1;\n const baseIndent = this.getLineIndentation(lineElement.querySelector('.line-content').textContent);\n\n while (currentIndex < lines.length) {\n const nextLine = lines[currentIndex];\n const nextContent = nextLine.querySelector('.line-content').textContent;\n const nextIndent = this.getLineIndentation(nextContent);\n\n // Stop if we hit a line at the same or lower indentation level\n if (nextContent.trim() && nextIndent <= baseIndent) {\n break;\n }\n\n nextLine.classList.add('collapsed-content');\n currentIndex++;\n }\n\n // Add collapsed placeholder\n const placeholder = document.createElement('div');\n placeholder.className = 'source-line collapsed-placeholder';\n placeholder.innerHTML = `\n <span class=\"line-number\"></span>\n <span class=\"collapse-indicator none\"></span>\n <span class=\"line-content\"> ... (collapsed)</span>\n `;\n lineElement.insertAdjacentElement('afterend', placeholder);\n }\n\n /**\n * Expand a source section\n */\n expandSourceSection(lineElement) {\n const indicator = lineElement.querySelector('.collapse-indicator');\n indicator.classList.remove('collapsed');\n indicator.classList.add('expanded');\n\n // Show hidden lines\n const container = lineElement.parentElement;\n const lines = Array.from(container.children);\n\n lines.forEach(line => {\n if (line.classList.contains('collapsed-content')) {\n line.classList.remove('collapsed-content');\n }\n });\n\n // Remove placeholder\n const placeholder = lineElement.nextElementSibling;\n if (placeholder && placeholder.classList.contains('collapsed-placeholder')) {\n placeholder.remove();\n }\n }\n\n /**\n * Get indentation level of a line\n */\n getLineIndentation(content) {\n const match = content.match(/^(\\s*)/);\n return match ? match[1].length : 0;\n }\n\n /**\n * Auto-expand file node to show AST tree after analysis\n */\n autoExpandFileWithAST(filePath, fileNode) {\n console.log('🌳 [AST EXPANSION] Auto-expanding file with AST:', {\n filePath: filePath,\n hasChildren: !!(fileNode && fileNode.children && fileNode.children.length > 0)\n });\n\n if (!fileNode || !fileNode.children || fileNode.children.length === 0) {\n console.log('⚠️ [AST EXPANSION] No children to expand');\n return;\n }\n\n // Find the D3 node for this file\n const d3Node = this.findD3NodeByPath(filePath);\n if (!d3Node) {\n console.log('⚠️ [AST EXPANSION] D3 node not found for path:', filePath);\n return;\n }\n\n // Rebuild the D3 hierarchy to include new children\n this.root = d3.hierarchy(this.treeData);\n\n // Find the updated D3 node\n const updatedD3Node = this.findD3NodeByPath(filePath);\n if (updatedD3Node) {\n // Expand the file node to show AST elements\n if (updatedD3Node._children || (updatedD3Node.children && updatedD3Node.children.length === 0)) {\n updatedD3Node.children = updatedD3Node._children || updatedD3Node.children;\n updatedD3Node._children = null;\n updatedD3Node.data.expanded = true;\n\n console.log('✅ [AST EXPANSION] Expanded file node to show AST elements:', {\n filePath: filePath,\n childrenCount: updatedD3Node.children ? updatedD3Node.children.length : 0\n });\n\n // Update the visualization\n this.update(this.root);\n\n // Show notification about AST expansion\n const fileName = filePath.split('/').pop();\n const astCount = updatedD3Node.children ? updatedD3Node.children.length : 0;\n this.showNotification(`📊 ${fileName} - AST tree expanded with ${astCount} elements`, 'success');\n this.updateBreadcrumb(`${fileName} - Code structure visible in tree`, 'success');\n }\n }\n }\n\n /**\n * Display file content in the unified data viewer\n */\n displayFileInDataViewer(d) {\n console.log('📊 [DATA VIEWER] Displaying file in data viewer:', {\n fileName: d.data.name,\n filePath: d.data.path,\n fileType: d.data.type\n });\n\n // Create file data object for unified data viewer\n const fileData = {\n file_path: d.data.path,\n name: d.data.name,\n type: 'file',\n size: d.data.size || 0,\n extension: this.getFileExtension(d.data.path),\n language: this.detectLanguage(d.data.path),\n operations: [{\n operation: 'view',\n timestamp: new Date().toISOString(),\n source: 'code_tree_click'\n }],\n // Add metadata for better display\n metadata: {\n clicked_from: 'code_tree',\n node_type: d.data.type,\n has_ast: d.data.analyzed || false,\n tree_path: this.getNodePath(d)\n }\n };\n\n // Use the unified data viewer to display file information\n if (window.unifiedDataViewer) {\n window.unifiedDataViewer.display(fileData, 'file_operation');\n console.log('✅ [DATA VIEWER] File data displayed in unified viewer');\n } else {\n console.warn('⚠️ [DATA VIEWER] UnifiedDataViewer not available');\n }\n\n // Update module header to show current file\n const moduleHeader = document.querySelector('.module-data-header h5');\n if (moduleHeader) {\n const fileName = d.data.name;\n const fileIcon = this.getFileIcon(d.data.path);\n moduleHeader.innerHTML = `${fileIcon} File: ${fileName}`;\n }\n\n // Add a small delay, then check if user wants to open full file viewer\n // This gives them time to see the data viewer content first\n setTimeout(() => {\n this.offerFileViewerOption(d);\n }, 1000);\n }\n\n /**\n * Offer option to open file in full viewer modal\n */\n offerFileViewerOption(d) {\n // Only offer for text files that can be displayed\n if (!this.isTextFile(d.data.path)) {\n return;\n }\n\n // Create a subtle notification with option to open full viewer\n const fileName = d.data.name;\n const notification = document.createElement('div');\n notification.className = 'file-viewer-offer';\n notification.innerHTML = `\n <div class=\"offer-content\">\n <span class=\"offer-text\">📄 ${fileName} loaded in data viewer</span>\n <button class=\"offer-button\" onclick=\"this.parentElement.parentElement.remove(); window.showFileViewerModal && window.showFileViewerModal('${d.data.path}')\">\n 🔍 Open Full Viewer\n </button>\n <button class=\"offer-close\" onclick=\"this.parentElement.parentElement.remove()\">×</button>\n </div>\n `;\n\n // Style the notification\n notification.style.cssText = `\n position: fixed;\n top: 20px;\n right: 20px;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n padding: 12px;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);\n z-index: 1000;\n max-width: 300px;\n font-size: 14px;\n `;\n\n // Style the button\n const style = document.createElement('style');\n style.textContent = `\n .offer-content {\n display: flex;\n align-items: center;\n gap: 8px;\n }\n .offer-text {\n flex: 1;\n color: #4a5568;\n }\n .offer-button {\n background: #4299e1;\n color: white;\n border: none;\n border-radius: 4px;\n padding: 4px 8px;\n font-size: 12px;\n cursor: pointer;\n transition: background 0.2s;\n }\n .offer-button:hover {\n background: #3182ce;\n }\n .offer-close {\n background: none;\n border: none;\n color: #a0aec0;\n cursor: pointer;\n font-size: 16px;\n padding: 0;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .offer-close:hover {\n color: #718096;\n }\n `;\n\n document.head.appendChild(style);\n document.body.appendChild(notification);\n\n // Auto-remove after 5 seconds\n setTimeout(() => {\n if (notification.parentElement) {\n notification.remove();\n }\n }, 5000);\n }\n\n /**\n * Check if file is a text file that can be displayed\n */\n isTextFile(filePath) {\n if (!filePath) return false;\n\n const ext = this.getFileExtension(filePath);\n const textExtensions = [\n 'py', 'js', 'ts', 'jsx', 'tsx', 'html', 'css', 'json', 'md', 'txt',\n 'yml', 'yaml', 'xml', 'sql', 'sh', 'bash', 'dockerfile', 'makefile',\n 'gitignore', 'readme', 'cfg', 'conf', 'ini', 'toml', 'lock'\n ];\n\n return textExtensions.includes(ext) ||\n textExtensions.includes(filePath.toLowerCase().split('/').pop());\n }\n\n /**\n * Get the full path from root to the given node\n */\n getNodePath(d) {\n const path = [];\n let current = d;\n while (current) {\n if (current.data && current.data.name) {\n path.unshift(current.data.name);\n }\n current = current.parent;\n }\n return path.join(' > ');\n }\n\n /**\n * Get file extension from path\n */\n getFileExtension(filePath) {\n if (!filePath) return '';\n const parts = filePath.split('.');\n return parts.length > 1 ? parts.pop().toLowerCase() : '';\n }\n\n /**\n * Get descriptive file type for user messages\n */\n getFileTypeDescription(fileName) {\n if (!fileName) return 'File';\n\n const ext = this.getFileExtension(fileName);\n const baseName = fileName.toLowerCase();\n\n // Special cases\n if (baseName.endsWith('__init__.py')) {\n return 'Python package initialization';\n }\n if (baseName === 'makefile') {\n return 'Build configuration';\n }\n if (baseName.includes('config') || baseName.includes('settings')) {\n return 'Configuration file';\n }\n if (baseName.includes('test') || baseName.includes('spec')) {\n return 'Test file';\n }\n\n // By extension\n const typeMap = {\n 'py': 'Python file',\n 'js': 'JavaScript file',\n 'ts': 'TypeScript file',\n 'jsx': 'React component',\n 'tsx': 'React TypeScript component',\n 'html': 'HTML document',\n 'css': 'Stylesheet',\n 'json': 'JSON data',\n 'md': 'Markdown document',\n 'txt': 'Text file',\n 'yml': 'YAML configuration',\n 'yaml': 'YAML configuration',\n 'xml': 'XML document',\n 'sql': 'SQL script',\n 'sh': 'Shell script',\n 'bash': 'Bash script',\n 'toml': 'TOML configuration',\n 'ini': 'INI configuration'\n };\n\n return typeMap[ext] || 'File';\n }\n\n /**\n * Count different types of AST elements\n */\n getElementCounts(elements) {\n const counts = {\n classes: 0,\n functions: 0,\n methods: 0,\n total: elements.length\n };\n\n elements.forEach(elem => {\n if (elem.type === 'class') {\n counts.classes++;\n if (elem.methods) {\n counts.methods += elem.methods.length;\n }\n } else if (elem.type === 'function') {\n counts.functions++;\n }\n });\n\n return counts;\n }\n\n /**\n * Format element counts into a readable summary\n */\n formatElementSummary(counts) {\n const parts = [];\n\n if (counts.classes > 0) {\n parts.push(`${counts.classes} class${counts.classes !== 1 ? 'es' : ''}`);\n }\n if (counts.functions > 0) {\n parts.push(`${counts.functions} function${counts.functions !== 1 ? 's' : ''}`);\n }\n if (counts.methods > 0) {\n parts.push(`${counts.methods} method${counts.methods !== 1 ? 's' : ''}`);\n }\n\n if (parts.length === 0) {\n return 'Structural elements for tree view';\n } else if (parts.length === 1) {\n return parts[0] + ' found';\n } else if (parts.length === 2) {\n return parts.join(' and ') + ' found';\n } else {\n return parts.slice(0, -1).join(', ') + ', and ' + parts[parts.length - 1] + ' found';\n }\n }\n\n /**\n * Get file icon based on file type\n */\n getFileIcon(filePath) {\n if (!filePath) return '📄';\n\n const ext = this.getFileExtension(filePath);\n const iconMap = {\n 'py': '🐍',\n 'js': '📜',\n 'ts': '📘',\n 'jsx': '⚛️',\n 'tsx': '⚛️',\n 'html': '🌐',\n 'css': '🎨',\n 'json': '📋',\n 'md': '📝',\n 'txt': '📄',\n 'yml': '⚙️',\n 'yaml': '⚙️',\n 'xml': '📰',\n 'sql': '🗃️',\n 'sh': '🐚',\n 'bash': '🐚',\n 'dockerfile': '🐳',\n 'makefile': '🔨',\n 'gitignore': '🚫',\n 'readme': '📖'\n };\n\n return iconMap[ext] || iconMap[filePath.toLowerCase().split('/').pop()] || '📄';\n }\n\n /**\n * Handle click on source line with AST elements\n */\n onSourceLineClick(lineElement, astElements, node) {\n console.log('🎯 [SOURCE LINE CLICK] Line clicked:', {\n line: lineElement.dataset.lineNumber,\n astElements: astElements.length\n });\n\n // Highlight the clicked line\n this.highlightSourceLine(lineElement);\n\n // Show AST details for this line\n if (astElements.length > 0) {\n this.showASTElementDetails(astElements[0], node);\n }\n\n // If this is a collapsible line, also toggle it\n if (lineElement.classList.contains('collapsible')) {\n this.toggleSourceSection(lineElement);\n }\n }\n\n /**\n * Highlight a source line\n */\n highlightSourceLine(lineElement) {\n // Remove previous highlights\n if (this.currentSourceContainer) {\n const lines = this.currentSourceContainer.querySelectorAll('.source-line');\n lines.forEach(line => line.classList.remove('highlighted'));\n }\n\n // Add highlight to clicked line\n lineElement.classList.add('highlighted');\n }\n\n /**\n * Show AST element details\n */\n showASTElementDetails(astElement, node) {\n // This could open a detailed view or update another panel\n console.log('📋 [AST DETAILS] Showing details for:', astElement);\n\n // For now, just log the details\n // In a full implementation, this might update a details panel\n }\n\n /**\n * Expand all collapsible sections in source viewer\n */\n expandAllSource() {\n if (!this.currentSourceContainer) return;\n\n const collapsibleLines = this.currentSourceContainer.querySelectorAll('.source-line.collapsible');\n collapsibleLines.forEach(line => {\n const indicator = line.querySelector('.collapse-indicator');\n if (indicator.classList.contains('collapsed')) {\n this.expandSourceSection(line);\n }\n });\n }\n\n /**\n * Collapse all collapsible sections in source viewer\n */\n collapseAllSource() {\n if (!this.currentSourceContainer) return;\n\n const collapsibleLines = this.currentSourceContainer.querySelectorAll('.source-line.collapsible');\n collapsibleLines.forEach(line => {\n const indicator = line.querySelector('.collapse-indicator');\n if (indicator.classList.contains('expanded')) {\n this.collapseSourceSection(line);\n }\n });\n }\n}\n\n// Export for use in other modules\nwindow.CodeTree = CodeTree;\n\n// Auto-initialize when DOM is ready\ndocument.addEventListener('DOMContentLoaded', () => {\n // Check if we're on a page with code tree container\n if (document.getElementById('code-tree-container')) {\n window.codeTree = new CodeTree();\n\n // Expose debug functions globally for troubleshooting\n window.debugCodeTree = {\n clearLoadingState: () => window.codeTree?.clearLoadingState(),\n showLoadingNodes: () => {\n console.log('Current loading nodes:', Array.from(window.codeTree?.loadingNodes || []));\n return Array.from(window.codeTree?.loadingNodes || []);\n },\n resetTree: () => {\n if (window.codeTree) {\n window.codeTree.clearLoadingState();\n window.codeTree.initializeTreeData();\n console.log('Tree reset complete');\n }\n },\n focusOnPath: (path) => {\n if (window.codeTree) {\n const node = window.codeTree.findD3NodeByPath(path);\n if (node) {\n window.codeTree.focusOnDirectory(node);\n console.log('Focused on:', path);\n } else {\n console.log('Node not found:', path);\n }\n }\n },\n unfocus: () => window.codeTree?.unfocusDirectory()\n };\n\n // Listen for tab changes to initialize when code tab is selected\n document.addEventListener('click', (e) => {\n if (e.target.matches('[data-tab=\"code\"]')) {\n setTimeout(() => {\n if (window.codeTree && !window.codeTree.initialized) {\n window.codeTree.initialize();\n } else if (window.codeTree) {\n window.codeTree.renderWhenVisible();\n }\n }, 100);\n }\n });\n }\n});\n"],"names":["CodeTree","constructor","this","tooltipService","window","domHelpers","eventBus","logger","createComponentLogger","console","treeUtils","treeConstants","treeSearch","treeBreadcrumb","container","svg","treeData","root","treeLayout","treeGroup","nodes","Map","stats","files","classes","functions","methods","lines","isRadialLayout","margin","DEFAULT_MARGIN","top","right","bottom","left","width","DEFAULT_WIDTH","height","DEFAULT_HEIGHT","radius","Math","min","nodeId","duration","ANIMATION_DURATION","languageFilter","searchTerm","tooltip","initialized","analyzing","selectedNode","socket","autoDiscovered","zoom","structuredDataContent","selectedASTItem","activeNode","loadingNodes","Set","bulkLoadMode","expandedPaths","focusedNode","horizontalNodes","centralSpine","onNodeClick","bind","showTooltip","hideTooltip","initialize","document","getElementById","error","tabPanel","workingDir","getWorkingDirectory","showNoWorkingDirectoryMessage","setupControls","initializeTreeData","subscribeToEvents","initializeStructuredData","updateActivityTicker","classList","contains","createVisualization","update","autoDiscoverRootLevel","renderWhenVisible","removeNoWorkingDirectoryMessage","addEventListener","e","target","value","filterTree","searchBox","toLowerCase","toggleLegendBtn","toggleLegend","onWorkingDirectoryChanged","detail","directory","newDirectory","clear","updateStats","showLoading","loadingDiv","createElement","id","innerHTML","appendChild","remove","hideLoading","add","d3","select","selectAll","addTreeControls","node","containerNode","containerWidth","clientWidth","containerHeight","clientHeight","append","attr","centerX","centerY","cluster","size","PI","separation","a","b","parent","depthFactor","max","depth","siblingCount","children","length","siblingFactor","radiusFactor","tree","nodeSize","scaleExtent","on","event","transform","adjustTextSizeForZoom","k","updateZoomLevel","call","addZoomKeyboardShortcuts","log","addVisualizationControls","style","clearD3Visualization","name","path","type","isDirectory","loaded","expanded","hasChildren","isRoot","hierarchy","x0","y0","connected","setupEventHandlers","dashboard","socketClient","io","warn","startsWith","match","showNotification","hasListeners","dirName","split","pop","updateBreadcrumb","apiUrl","location","origin","encodeURIComponent","fetch","then","response","ok","Error","status","statusText","json","data","contents","Array","isArray","map","item","is_directory","forEach","child","_children","fileCount","filter","dirCount","addEventToDisplay","catch","message","requestPayload","languages","getSelectedLanguages","ignore_patterns","request_id","Date","now","emit","analyzeCode","cancelAnalysis","toolbar","text","expandAll","collapseAll","toggleBulkLoad","toggleLayout","zoomIn","zoomOut","resetZoom","searchTree","key","addBreadcrumb","updateBreadcrumbPath","currentPath","pathDiv","segments","s","segment","index","parentPath","slice","join","navigateToPath","expandNode","collapseNode","button","classed","query","trim","matchingNodes","searchNode","includes","push","matchNode","d","expandPathToNode","targetNode","pathToExpand","current","unshift","createEventsDisplay","eventsContainer","treeContainer","className","display","clearEventsDisplay","eventEl","borderLeftColor","timestamp","toLocaleTimeString","scrollTop","scrollHeight","onAnalysisAccepted","onAnalysisQueued","onAnalysisStart","onAnalysisComplete","onAnalysisCancelled","onAnalysisError","onTopLevelDiscovered","onDirectoryDiscovered","onFileDiscovered","onFileAnalyzed","onNodeFound","onProgressUpdate","connectionStable","analysisTimeouts","timeout","clearTimeout","delete","searchPath","substring","replace","findNodeByPath","d3Node","findD3NodeByPath","has","removeLoadingPulse","childPath","childName","analyzed","oldRoot","preserveExpansionState","updatedD3Node","directories","items","language","detectLanguage","rootNode","currentChildren","has_code","childData","childNode","Object","keys","childrenCount","c","fullEventData","nodeFound","nodeName","nodePath","nodeChildren","dataHasChildren","dataChildrenLength","logAllPaths","dataChildrenIsArray","dataChildrenValue","d3ChildrenCount","dataChildrenCount","childPaths","dataChildren","dataKeys","fullData","nodeExists","pathParts","p","forceAdd","dirNode","addNodeToTree","originalPath","allTreePaths","getAllTreePaths","fileName","fileNode","elements","complexity","elementsDetail","elem","line","elementCounts","getElementCounts","summary","formatElementSummary","fileType","getFileTypeDescription","get","docstring","m","filePath","autoExpandFileWithAST","updatedFileNode","childNames","typeIcon","nodeInfo","class","function","method","module","file","parent_path","file_path","parts","elementType","charAt","toUpperCase","progress","progressBar","querySelector","position","onInfoEvent","debugMode","showFilterEvents","debug","reason","showCacheEvents","eventLogEnabled","recentEvents","toISOString","notification","textContent","zIndex","setTimeout","animation","parentNode","existingNode","find","assign","set","found","indent","paths","descendants","newRoot","expansionMap","statsElements","entries","toLocaleString","progressText","breadcrumbContent","analyzeFileHTTP","mockAnalysisResult","createMockAnalysisData","ext","reduce","sum","selectedLanguages","checkboxes","querySelectorAll","cb","checked","py","js","ts","jsx","tsx","java","cpp","cs","rb","go","rs","php","swift","kt","scala","r","sh","ps1","toggleButton","radialPoint","x","y","cos","sin","applySingletonHorizontalLayout","identifyCentralSpine","from","currentNode","mainChild","selectMainChild","isNodeDirectory","findSingletonChains","chains","processed","chain","n","layoutChainHorizontally","horizontalSpacing","originalX","originalY","startY","vertical","horizontal","source","links","nodeEnter","enter","eventTarget","tagName","thisContext","hasOnNodeClick","getNodeColor","getNodeStrokeColor","baseClass","maxLength","getNodeIcon","count","nodeUpdate","merge","transition","isRadial","each","selection","angle","nodeExit","exit","link","insert","o","radialDiagonal","diagonal","currentTransform","zoomTransform","centerOnNode","centerOnNodeRadial","highlightActiveNode","allCircles","activeNodeCircle","addLoadingPulse","pulseAnimation","interrupt","showWithParent","parentCircle","clickId","random","isBound","loadingNodesSize","updateStructuredData","stopPropagation","stack","loadedType","notLoaded","shouldLoad","displayFileInDataViewer","fileLanguage","detectedLanguage","isLanguageSelected","shouldAnalyze","fullPath","ensureFullPath","hasSocket","socketConnected","socketId","analysisTimeout","closest","loadingNodesContent","pathType","loadingNodesType","hasMethod","isDuplicate","pathBeingChecked","pathInSet","nodeType","pathToDelete","loadingNodesBefore","deleted","pathDeleted","wasDeleted","loadingNodesAfter","exists","focusOnDirectory","nodeData","highlightNode","result","linkRadial","baseColor","color","darker","info","html","pageX","pageY","_hidden","expandRecursive","collapseRecursive","focusedRoot","tempRoot","originalRoot","addBackButton","unfocusDirectory","removeBackButton","empty","bounds","getBBox","fullWidth","fullHeight","midX","midY","scale","translate","zoomIdentity","scaleBy","zoomDisplay","round","zoomScale","textScale","cleanTransform","codeTab","ctrlKey","metaKey","preventDefault","isSourceFile","some","endsWith","showSourceViewer","sourceViewer","header","content","expandAllSource","collapseAllSource","loadSourceContent","focusOnNode","getNodePath","legend","workingDirectoryManager","getCurrentWorkingDir","workingDirPath","pathText","messageDiv","cssText","messageIcon","h3","background","changeDirBtn","click","showChangeDirDialog","clearLoadingState","resetLoadingFlags","exportTree","exportData","workingDirectory","blob","Blob","JSON","stringify","url","URL","createObjectURL","href","download","revokeObjectURL","breadcrumb","icon","updateTicker","ticker","opacity","parentElement","allElements","el","moduleViewer","moduleDataContent","contentElement","showASTNodeChildren","showASTFileDetails","showASTNodeDetails","childrenToShow","showASTEmptyState","createASTDataViewerItem","details","label","formatFileSize","createASTDetailItem","dataset","detailParts","complexityLevel","getComplexityLevel","selectASTDataViewerItem","previousSelected","variable","import","bytes","i","floor","parseFloat","pow","toFixed","contentContainer","sourceContent","readSourceFile","astElements","renderSourceWithAST","generatePlaceholderSource","astMap","createASTLineMap","lineNumber","lineElement","createSourceLine","currentSourceContainer","currentASTElements","lineMap","element","lineDiv","hasAST","isCollapsible","isCollapsibleLine","lineNumberSpan","collapseIndicator","toggleSourceSection","lineContentSpan","applySyntaxHighlighting","onSourceLineClick","trimmed","highlighted","replacements","currentFilePath","jsonKeys","exec","start","end","replacement","jsonStrings","colonIndex","indexOf","jsonNumbers","numberStart","jsonLiterals","keywords","stringPattern","commentPattern","sort","rep","before","after","lastIndexOf","collapseSourceSection","expandSourceSection","indicator","parseInt","currentIndex","baseIndent","getLineIndentation","nextLine","nextContent","nextIndent","placeholder","insertAdjacentElement","nextElementSibling","astCount","fileData","extension","getFileExtension","operations","operation","metadata","clicked_from","node_type","has_ast","tree_path","unifiedDataViewer","moduleHeader","fileIcon","getFileIcon","offerFileViewerOption","isTextFile","head","body","textExtensions","baseName","css","md","txt","yml","yaml","xml","sql","bash","toml","ini","counts","total","iconMap","dockerfile","makefile","gitignore","readme","highlightSourceLine","showASTElementDetails","astElement","codeTree","debugCodeTree","showLoadingNodes","resetTree","focusOnPath","unfocus","matches"],"mappings":"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"}