claude-mpm 5.0.9__py3-none-any.whl → 5.4.41__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 (263) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +4 -0
  3. claude_mpm/agents/BASE_AGENT.md +164 -0
  4. claude_mpm/agents/{PM_INSTRUCTIONS_TEACH.md → CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md} +721 -41
  5. claude_mpm/agents/MEMORY.md +1 -1
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +468 -468
  7. claude_mpm/agents/WORKFLOW.md +5 -254
  8. claude_mpm/agents/agent_loader.py +13 -44
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/frontmatter_validator.py +70 -2
  11. claude_mpm/agents/templates/circuit-breakers.md +431 -45
  12. claude_mpm/cli/__init__.py +0 -1
  13. claude_mpm/cli/__main__.py +4 -0
  14. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  15. claude_mpm/cli/commands/agent_state_manager.py +18 -27
  16. claude_mpm/cli/commands/agents.py +175 -37
  17. claude_mpm/cli/commands/auto_configure.py +723 -236
  18. claude_mpm/cli/commands/config.py +88 -2
  19. claude_mpm/cli/commands/configure.py +1262 -157
  20. claude_mpm/cli/commands/configure_agent_display.py +25 -6
  21. claude_mpm/cli/commands/mpm_init/core.py +225 -46
  22. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  23. claude_mpm/cli/commands/mpm_init/prompts.py +280 -0
  24. claude_mpm/cli/commands/postmortem.py +1 -1
  25. claude_mpm/cli/commands/profile.py +277 -0
  26. claude_mpm/cli/commands/skills.py +214 -189
  27. claude_mpm/cli/commands/summarize.py +413 -0
  28. claude_mpm/cli/executor.py +21 -3
  29. claude_mpm/cli/interactive/agent_wizard.py +85 -10
  30. claude_mpm/cli/parsers/agents_parser.py +54 -9
  31. claude_mpm/cli/parsers/auto_configure_parser.py +13 -138
  32. claude_mpm/cli/parsers/base_parser.py +12 -0
  33. claude_mpm/cli/parsers/config_parser.py +153 -83
  34. claude_mpm/cli/parsers/profile_parser.py +148 -0
  35. claude_mpm/cli/parsers/skills_parser.py +3 -2
  36. claude_mpm/cli/startup.py +879 -149
  37. claude_mpm/commands/mpm-config.md +28 -0
  38. claude_mpm/commands/mpm-doctor.md +9 -22
  39. claude_mpm/commands/mpm-help.md +5 -287
  40. claude_mpm/commands/mpm-init.md +81 -507
  41. claude_mpm/commands/mpm-monitor.md +15 -402
  42. claude_mpm/commands/mpm-organize.md +120 -0
  43. claude_mpm/commands/mpm-postmortem.md +6 -108
  44. claude_mpm/commands/mpm-session-resume.md +12 -363
  45. claude_mpm/commands/mpm-status.md +5 -69
  46. claude_mpm/commands/mpm-ticket-view.md +52 -495
  47. claude_mpm/commands/mpm-version.md +5 -107
  48. claude_mpm/config/agent_sources.py +27 -0
  49. claude_mpm/core/config.py +2 -4
  50. claude_mpm/core/framework/formatters/content_formatter.py +3 -13
  51. claude_mpm/core/framework/loaders/agent_loader.py +8 -5
  52. claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
  53. claude_mpm/core/framework_loader.py +4 -2
  54. claude_mpm/core/logger.py +13 -0
  55. claude_mpm/core/optimized_startup.py +59 -0
  56. claude_mpm/core/output_style_manager.py +173 -43
  57. claude_mpm/core/shared/config_loader.py +1 -1
  58. claude_mpm/core/socketio_pool.py +3 -3
  59. claude_mpm/core/unified_agent_registry.py +134 -16
  60. claude_mpm/core/unified_config.py +22 -0
  61. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  62. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +1 -0
  63. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +1 -0
  64. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +1 -0
  65. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +1 -0
  66. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +1 -0
  67. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +2 -0
  68. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DjhvlsAc.js +1 -0
  69. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/N4qtv3Hx.js +2 -0
  70. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uj46x2Wr.js +1 -0
  71. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +2 -0
  72. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +1 -0
  73. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.CAGBuiOw.js +1 -0
  74. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +1 -0
  75. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +10 -0
  76. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  77. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  78. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  79. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  80. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  87. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  88. claude_mpm/hooks/claude_hooks/event_handlers.py +211 -78
  89. claude_mpm/hooks/claude_hooks/hook_handler.py +155 -1
  90. claude_mpm/hooks/claude_hooks/installer.py +33 -10
  91. claude_mpm/hooks/claude_hooks/memory_integration.py +28 -0
  92. claude_mpm/hooks/claude_hooks/response_tracking.py +2 -3
  93. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  94. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  95. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  96. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  97. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  98. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  99. claude_mpm/hooks/claude_hooks/services/connection_manager.py +30 -6
  100. claude_mpm/hooks/memory_integration_hook.py +46 -1
  101. claude_mpm/init.py +63 -19
  102. claude_mpm/models/agent_definition.py +7 -0
  103. claude_mpm/models/git_repository.py +3 -3
  104. claude_mpm/scripts/claude-hook-handler.sh +58 -18
  105. claude_mpm/scripts/launch_monitor.py +93 -13
  106. claude_mpm/scripts/start_activity_logging.py +0 -0
  107. claude_mpm/services/agents/agent_builder.py +3 -3
  108. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  109. claude_mpm/services/agents/agent_review_service.py +280 -0
  110. claude_mpm/services/agents/cache_git_manager.py +6 -6
  111. claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
  112. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -5
  113. claude_mpm/services/agents/deployment/agent_template_builder.py +5 -3
  114. claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
  115. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +320 -29
  116. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +546 -68
  117. claude_mpm/services/agents/git_source_manager.py +36 -2
  118. claude_mpm/services/agents/loading/base_agent_manager.py +1 -13
  119. claude_mpm/services/agents/recommender.py +5 -3
  120. claude_mpm/services/agents/single_tier_deployment_service.py +2 -2
  121. claude_mpm/services/agents/sources/git_source_sync_service.py +13 -6
  122. claude_mpm/services/agents/startup_sync.py +22 -2
  123. claude_mpm/services/agents/toolchain_detector.py +10 -6
  124. claude_mpm/services/analysis/__init__.py +11 -1
  125. claude_mpm/services/analysis/clone_detector.py +1030 -0
  126. claude_mpm/services/command_deployment_service.py +81 -10
  127. claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
  128. claude_mpm/services/diagnostics/checks/agent_sources_check.py +1 -1
  129. claude_mpm/services/event_bus/config.py +3 -1
  130. claude_mpm/services/git/git_operations_service.py +101 -16
  131. claude_mpm/services/monitor/daemon.py +9 -2
  132. claude_mpm/services/monitor/daemon_manager.py +39 -3
  133. claude_mpm/services/monitor/management/lifecycle.py +8 -1
  134. claude_mpm/services/monitor/server.py +698 -22
  135. claude_mpm/services/pm_skills_deployer.py +676 -0
  136. claude_mpm/services/profile_manager.py +331 -0
  137. claude_mpm/services/project/project_organizer.py +4 -0
  138. claude_mpm/services/self_upgrade_service.py +120 -12
  139. claude_mpm/services/skills/__init__.py +3 -0
  140. claude_mpm/services/skills/git_skill_source_manager.py +130 -2
  141. claude_mpm/services/skills/selective_skill_deployer.py +704 -0
  142. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  143. claude_mpm/services/skills_deployer.py +126 -9
  144. claude_mpm/services/socketio/dashboard_server.py +1 -0
  145. claude_mpm/services/socketio/event_normalizer.py +51 -6
  146. claude_mpm/services/socketio/server/core.py +386 -108
  147. claude_mpm/services/version_control/git_operations.py +103 -0
  148. claude_mpm/skills/skill_manager.py +92 -3
  149. claude_mpm/utils/agent_dependency_loader.py +14 -2
  150. claude_mpm/utils/agent_filters.py +17 -44
  151. claude_mpm/utils/gitignore.py +3 -0
  152. claude_mpm/utils/migration.py +4 -4
  153. claude_mpm/utils/robust_installer.py +47 -3
  154. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/METADATA +57 -87
  155. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/RECORD +160 -211
  156. claude_mpm-5.4.41.dist-info/entry_points.txt +5 -0
  157. claude_mpm-5.4.41.dist-info/licenses/LICENSE +94 -0
  158. claude_mpm-5.4.41.dist-info/licenses/LICENSE-FAQ.md +153 -0
  159. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -292
  160. claude_mpm/agents/BASE_DOCUMENTATION.md +0 -53
  161. claude_mpm/agents/BASE_OPS.md +0 -219
  162. claude_mpm/agents/BASE_PM.md +0 -480
  163. claude_mpm/agents/BASE_PROMPT_ENGINEER.md +0 -787
  164. claude_mpm/agents/BASE_QA.md +0 -167
  165. claude_mpm/agents/BASE_RESEARCH.md +0 -53
  166. claude_mpm/agents/base_agent_loader.py +0 -601
  167. claude_mpm/cli/commands/agents_detect.py +0 -380
  168. claude_mpm/cli/commands/agents_recommend.py +0 -309
  169. claude_mpm/cli/ticket_cli.py +0 -35
  170. claude_mpm/commands/mpm-agents-auto-configure.md +0 -278
  171. claude_mpm/commands/mpm-agents-detect.md +0 -177
  172. claude_mpm/commands/mpm-agents-list.md +0 -131
  173. claude_mpm/commands/mpm-agents-recommend.md +0 -223
  174. claude_mpm/commands/mpm-config-view.md +0 -150
  175. claude_mpm/commands/mpm-ticket-organize.md +0 -304
  176. claude_mpm/dashboard/analysis_runner.py +0 -455
  177. claude_mpm/dashboard/index.html +0 -13
  178. claude_mpm/dashboard/open_dashboard.py +0 -66
  179. claude_mpm/dashboard/static/css/activity.css +0 -1958
  180. claude_mpm/dashboard/static/css/connection-status.css +0 -370
  181. claude_mpm/dashboard/static/css/dashboard.css +0 -4701
  182. claude_mpm/dashboard/static/js/components/activity-tree.js +0 -1871
  183. claude_mpm/dashboard/static/js/components/agent-hierarchy.js +0 -777
  184. claude_mpm/dashboard/static/js/components/agent-inference.js +0 -956
  185. claude_mpm/dashboard/static/js/components/build-tracker.js +0 -333
  186. claude_mpm/dashboard/static/js/components/code-simple.js +0 -857
  187. claude_mpm/dashboard/static/js/components/connection-debug.js +0 -654
  188. claude_mpm/dashboard/static/js/components/diff-viewer.js +0 -891
  189. claude_mpm/dashboard/static/js/components/event-processor.js +0 -542
  190. claude_mpm/dashboard/static/js/components/event-viewer.js +0 -1155
  191. claude_mpm/dashboard/static/js/components/export-manager.js +0 -368
  192. claude_mpm/dashboard/static/js/components/file-change-tracker.js +0 -443
  193. claude_mpm/dashboard/static/js/components/file-change-viewer.js +0 -690
  194. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +0 -724
  195. claude_mpm/dashboard/static/js/components/file-viewer.js +0 -580
  196. claude_mpm/dashboard/static/js/components/hud-library-loader.js +0 -211
  197. claude_mpm/dashboard/static/js/components/hud-manager.js +0 -671
  198. claude_mpm/dashboard/static/js/components/hud-visualizer.js +0 -1718
  199. claude_mpm/dashboard/static/js/components/module-viewer.js +0 -2764
  200. claude_mpm/dashboard/static/js/components/session-manager.js +0 -579
  201. claude_mpm/dashboard/static/js/components/socket-manager.js +0 -368
  202. claude_mpm/dashboard/static/js/components/ui-state-manager.js +0 -749
  203. claude_mpm/dashboard/static/js/components/unified-data-viewer.js +0 -1824
  204. claude_mpm/dashboard/static/js/components/working-directory.js +0 -920
  205. claude_mpm/dashboard/static/js/connection-manager.js +0 -536
  206. claude_mpm/dashboard/static/js/dashboard.js +0 -1914
  207. claude_mpm/dashboard/static/js/extension-error-handler.js +0 -164
  208. claude_mpm/dashboard/static/js/socket-client.js +0 -1474
  209. claude_mpm/dashboard/static/js/tab-isolation-fix.js +0 -185
  210. claude_mpm/dashboard/static/socket.io.min.js +0 -7
  211. claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +0 -7
  212. claude_mpm/dashboard/templates/code_simple.html +0 -153
  213. claude_mpm/dashboard/templates/index.html +0 -606
  214. claude_mpm/dashboard/test_dashboard.html +0 -372
  215. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  216. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  217. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  218. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  219. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  220. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  221. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  222. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  223. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  224. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  225. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  226. claude_mpm/scripts/mcp_server.py +0 -75
  227. claude_mpm/scripts/mcp_wrapper.py +0 -39
  228. claude_mpm/services/mcp_gateway/__init__.py +0 -159
  229. claude_mpm/services/mcp_gateway/auto_configure.py +0 -369
  230. claude_mpm/services/mcp_gateway/config/__init__.py +0 -17
  231. claude_mpm/services/mcp_gateway/config/config_loader.py +0 -296
  232. claude_mpm/services/mcp_gateway/config/config_schema.py +0 -243
  233. claude_mpm/services/mcp_gateway/config/configuration.py +0 -429
  234. claude_mpm/services/mcp_gateway/core/__init__.py +0 -43
  235. claude_mpm/services/mcp_gateway/core/base.py +0 -312
  236. claude_mpm/services/mcp_gateway/core/exceptions.py +0 -253
  237. claude_mpm/services/mcp_gateway/core/interfaces.py +0 -443
  238. claude_mpm/services/mcp_gateway/core/process_pool.py +0 -977
  239. claude_mpm/services/mcp_gateway/core/singleton_manager.py +0 -315
  240. claude_mpm/services/mcp_gateway/core/startup_verification.py +0 -316
  241. claude_mpm/services/mcp_gateway/main.py +0 -589
  242. claude_mpm/services/mcp_gateway/registry/__init__.py +0 -12
  243. claude_mpm/services/mcp_gateway/registry/service_registry.py +0 -412
  244. claude_mpm/services/mcp_gateway/registry/tool_registry.py +0 -489
  245. claude_mpm/services/mcp_gateway/server/__init__.py +0 -15
  246. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +0 -414
  247. claude_mpm/services/mcp_gateway/server/stdio_handler.py +0 -372
  248. claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -712
  249. claude_mpm/services/mcp_gateway/tools/__init__.py +0 -36
  250. claude_mpm/services/mcp_gateway/tools/base_adapter.py +0 -485
  251. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +0 -789
  252. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +0 -654
  253. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +0 -456
  254. claude_mpm/services/mcp_gateway/tools/hello_world.py +0 -551
  255. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +0 -555
  256. claude_mpm/services/mcp_gateway/utils/__init__.py +0 -14
  257. claude_mpm/services/mcp_gateway/utils/package_version_checker.py +0 -160
  258. claude_mpm/services/mcp_gateway/utils/update_preferences.py +0 -170
  259. claude_mpm-5.0.9.dist-info/entry_points.txt +0 -10
  260. claude_mpm-5.0.9.dist-info/licenses/LICENSE +0 -21
  261. /claude_mpm/agents/{OUTPUT_STYLE.md → CLAUDE_MPM_OUTPUT_STYLE.md} +0 -0
  262. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/WHEEL +0 -0
  263. {claude_mpm-5.0.9.dist-info → claude_mpm-5.4.41.dist-info}/top_level.txt +0 -0
@@ -1,690 +0,0 @@
1
- /**
2
- * File Change Viewer Component
3
- *
4
- * Displays files edited by Claude in a tree structure grouped by working directory.
5
- * Integrates with FileChangeTracker for tracking changes and DiffViewer for showing diffs.
6
- * Supports session-based filtering and displays change indicators.
7
- */
8
-
9
- class FileChangeViewer {
10
- constructor() {
11
- this.modal = null;
12
- this.currentFile = null;
13
- this.initialized = false;
14
- this.fileTracker = null;
15
- this.diffViewer = null;
16
- this.currentSessionId = null;
17
- this.treeContainer = null;
18
- }
19
-
20
- /**
21
- * Initialize the file change viewer
22
- */
23
- initialize() {
24
- if (this.initialized) return;
25
-
26
- // Create dependent components
27
- this.fileTracker = new FileChangeTracker();
28
- this.diffViewer = new DiffViewer();
29
-
30
- this.createModal();
31
- this.setupEventHandlers();
32
- this.subscribeToEvents();
33
- this.injectStyles();
34
-
35
- this.initialized = true;
36
- console.log('File change viewer initialized');
37
- }
38
-
39
- /**
40
- * Create modal DOM structure
41
- */
42
- createModal() {
43
- const modalHtml = `
44
- <div class="file-change-modal" id="file-change-modal">
45
- <div class="file-change-content">
46
- <div class="file-change-header">
47
- <div class="file-change-title">
48
- <span class="title-icon">📝</span>
49
- <span class="title-text">Files Changed by Claude</span>
50
- </div>
51
- <div class="file-change-controls">
52
- <div class="session-filter">
53
- <label>Session:</label>
54
- <select id="file-session-filter" class="session-select">
55
- <option value="">All Sessions</option>
56
- </select>
57
- </div>
58
- <div class="file-stats" id="file-stats">
59
- <span class="stat-item">
60
- <span class="stat-icon">📄</span>
61
- <span class="stat-value" id="total-files">0</span>
62
- <span class="stat-label">files</span>
63
- </span>
64
- <span class="stat-item">
65
- <span class="stat-icon">✏️</span>
66
- <span class="stat-value" id="total-edits">0</span>
67
- <span class="stat-label">edits</span>
68
- </span>
69
- <span class="stat-item">
70
- <span class="stat-icon">💾</span>
71
- <span class="stat-value" id="total-writes">0</span>
72
- <span class="stat-label">writes</span>
73
- </span>
74
- </div>
75
- <button class="file-change-close" id="file-change-close">×</button>
76
- </div>
77
- </div>
78
- <div class="file-change-body">
79
- <div class="file-tree-container" id="file-tree-container">
80
- <!-- File tree will be inserted here -->
81
- </div>
82
- </div>
83
- </div>
84
- </div>
85
- `;
86
-
87
- // Add modal to body
88
- document.body.insertAdjacentHTML('beforeend', modalHtml);
89
- this.modal = document.getElementById('file-change-modal');
90
- this.treeContainer = document.getElementById('file-tree-container');
91
- }
92
-
93
- /**
94
- * Inject CSS styles
95
- */
96
- injectStyles() {
97
- const styleId = 'file-change-viewer-styles';
98
- if (document.getElementById(styleId)) return;
99
-
100
- const styles = `
101
- <style id="${styleId}">
102
- .file-change-modal {
103
- display: none;
104
- position: fixed;
105
- top: 0;
106
- left: 0;
107
- right: 0;
108
- bottom: 0;
109
- background: rgba(0, 0, 0, 0.5);
110
- z-index: 9999;
111
- padding: 20px;
112
- overflow: auto;
113
- }
114
-
115
- .file-change-modal.show {
116
- display: flex;
117
- align-items: center;
118
- justify-content: center;
119
- }
120
-
121
- .file-change-content {
122
- background: white;
123
- border-radius: 8px;
124
- width: 90%;
125
- max-width: 1200px;
126
- height: 80%;
127
- display: flex;
128
- flex-direction: column;
129
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
130
- }
131
-
132
- .file-change-header {
133
- display: flex;
134
- justify-content: space-between;
135
- align-items: center;
136
- padding: 16px 20px;
137
- border-bottom: 1px solid #e2e8f0;
138
- background: #f8fafc;
139
- border-radius: 8px 8px 0 0;
140
- }
141
-
142
- .file-change-title {
143
- display: flex;
144
- align-items: center;
145
- gap: 8px;
146
- font-size: 16px;
147
- font-weight: 600;
148
- color: #2d3748;
149
- }
150
-
151
- .title-icon {
152
- font-size: 20px;
153
- }
154
-
155
- .file-change-controls {
156
- display: flex;
157
- align-items: center;
158
- gap: 20px;
159
- }
160
-
161
- .session-filter {
162
- display: flex;
163
- align-items: center;
164
- gap: 8px;
165
- }
166
-
167
- .session-filter label {
168
- font-size: 13px;
169
- color: #4a5568;
170
- }
171
-
172
- .session-select {
173
- padding: 4px 8px;
174
- border: 1px solid #cbd5e0;
175
- border-radius: 4px;
176
- font-size: 13px;
177
- background: white;
178
- }
179
-
180
- .file-stats {
181
- display: flex;
182
- gap: 16px;
183
- }
184
-
185
- .stat-item {
186
- display: flex;
187
- align-items: center;
188
- gap: 4px;
189
- font-size: 13px;
190
- color: #4a5568;
191
- }
192
-
193
- .stat-icon {
194
- font-size: 14px;
195
- }
196
-
197
- .stat-value {
198
- font-weight: 600;
199
- color: #2d3748;
200
- }
201
-
202
- .file-change-close {
203
- width: 32px;
204
- height: 32px;
205
- border: none;
206
- background: transparent;
207
- font-size: 24px;
208
- cursor: pointer;
209
- color: #718096;
210
- display: flex;
211
- align-items: center;
212
- justify-content: center;
213
- border-radius: 4px;
214
- transition: all 0.2s;
215
- }
216
-
217
- .file-change-close:hover {
218
- background: #e2e8f0;
219
- color: #2d3748;
220
- }
221
-
222
- .file-change-body {
223
- flex: 1;
224
- overflow: auto;
225
- padding: 20px;
226
- background: #fafbfc;
227
- }
228
-
229
- .file-tree-container {
230
- display: flex;
231
- flex-direction: column;
232
- gap: 16px;
233
- }
234
-
235
- /* Directory groups */
236
- .directory-group {
237
- background: white;
238
- border: 1px solid #e2e8f0;
239
- border-radius: 6px;
240
- overflow: hidden;
241
- }
242
-
243
- .directory-header {
244
- display: flex;
245
- align-items: center;
246
- justify-content: space-between;
247
- padding: 12px 16px;
248
- background: #f8fafc;
249
- border-bottom: 1px solid #e2e8f0;
250
- cursor: pointer;
251
- transition: background 0.2s;
252
- }
253
-
254
- .directory-header:hover {
255
- background: #f1f5f9;
256
- }
257
-
258
- .directory-info {
259
- display: flex;
260
- align-items: center;
261
- gap: 8px;
262
- }
263
-
264
- .directory-icon {
265
- font-size: 16px;
266
- color: #4299e1;
267
- }
268
-
269
- .directory-path {
270
- font-family: 'SF Mono', Monaco, monospace;
271
- font-size: 13px;
272
- font-weight: 600;
273
- color: #2d3748;
274
- }
275
-
276
- .directory-stats {
277
- display: flex;
278
- gap: 12px;
279
- font-size: 12px;
280
- color: #718096;
281
- }
282
-
283
- .directory-files {
284
- padding: 12px;
285
- display: none;
286
- }
287
-
288
- .directory-group.expanded .directory-files {
289
- display: block;
290
- }
291
-
292
- .directory-group.expanded .directory-icon::before {
293
- content: '📂';
294
- }
295
-
296
- .directory-group:not(.expanded) .directory-icon::before {
297
- content: '📁';
298
- }
299
-
300
- /* File items */
301
- .file-item {
302
- display: flex;
303
- align-items: center;
304
- justify-content: space-between;
305
- padding: 10px 12px;
306
- background: #f8fafc;
307
- border: 1px solid #e2e8f0;
308
- border-radius: 4px;
309
- margin-bottom: 8px;
310
- cursor: pointer;
311
- transition: all 0.2s;
312
- }
313
-
314
- .file-item:hover {
315
- background: white;
316
- border-color: #4299e1;
317
- transform: translateX(4px);
318
- }
319
-
320
- .file-item:last-child {
321
- margin-bottom: 0;
322
- }
323
-
324
- .file-info {
325
- display: flex;
326
- align-items: center;
327
- gap: 8px;
328
- flex: 1;
329
- }
330
-
331
- .file-icon {
332
- font-size: 14px;
333
- }
334
-
335
- .file-name {
336
- font-family: 'SF Mono', Monaco, monospace;
337
- font-size: 13px;
338
- color: #2d3748;
339
- font-weight: 500;
340
- }
341
-
342
- .file-badges {
343
- display: flex;
344
- gap: 6px;
345
- }
346
-
347
- .file-badge {
348
- padding: 2px 6px;
349
- font-size: 11px;
350
- border-radius: 3px;
351
- font-weight: 600;
352
- }
353
-
354
- .badge-edit {
355
- background: #fef3c7;
356
- color: #92400e;
357
- }
358
-
359
- .badge-write {
360
- background: #dbeafe;
361
- color: #1e40af;
362
- }
363
-
364
- .badge-read {
365
- background: #e0e7ff;
366
- color: #3730a3;
367
- }
368
-
369
- .file-timestamp {
370
- font-size: 11px;
371
- color: #a0aec0;
372
- }
373
-
374
- /* Empty state */
375
- .empty-state {
376
- text-align: center;
377
- padding: 40px;
378
- color: #718096;
379
- }
380
-
381
- .empty-state-icon {
382
- font-size: 48px;
383
- margin-bottom: 16px;
384
- }
385
-
386
- .empty-state-text {
387
- font-size: 14px;
388
- }
389
- </style>
390
- `;
391
-
392
- document.head.insertAdjacentHTML('beforeend', styles);
393
- }
394
-
395
- /**
396
- * Setup event handlers
397
- */
398
- setupEventHandlers() {
399
- // Close button
400
- document.getElementById('file-change-close').addEventListener('click', () => {
401
- this.hide();
402
- });
403
-
404
- // Close on backdrop click
405
- this.modal.addEventListener('click', (e) => {
406
- if (e.target === this.modal) {
407
- this.hide();
408
- }
409
- });
410
-
411
- // Close on ESC key
412
- document.addEventListener('keydown', (e) => {
413
- if (e.key === 'Escape' && this.modal.classList.contains('show')) {
414
- this.hide();
415
- }
416
- });
417
-
418
- // Session filter
419
- document.getElementById('file-session-filter').addEventListener('change', (e) => {
420
- this.currentSessionId = e.target.value;
421
- this.updateFileTree();
422
- });
423
- }
424
-
425
- /**
426
- * Subscribe to events
427
- */
428
- subscribeToEvents() {
429
- // Subscribe to socket if available
430
- if (window.socket) {
431
- // We might want to listen for file operation events
432
- }
433
-
434
- // Listen for event viewer updates
435
- if (window.eventViewer) {
436
- // Hook into event updates to refresh our view
437
- const originalAddEvent = window.eventViewer.addEvent;
438
- window.eventViewer.addEvent = (event) => {
439
- originalAddEvent.call(window.eventViewer, event);
440
- if (this.modal && this.modal.classList.contains('show')) {
441
- this.updateFromEvents();
442
- }
443
- };
444
- }
445
- }
446
-
447
- /**
448
- * Show the file change viewer
449
- * @param {Array} events - Optional events to display
450
- */
451
- show(events = null) {
452
- if (!this.initialized) {
453
- this.initialize();
454
- }
455
-
456
- this.modal.classList.add('show');
457
-
458
- // Update with events
459
- if (events) {
460
- this.fileTracker.updateEvents(events);
461
- } else if (window.eventViewer) {
462
- this.fileTracker.updateEvents(window.eventViewer.events);
463
- }
464
-
465
- // Update session filter
466
- this.updateSessionFilter();
467
-
468
- // Display file tree
469
- this.updateFileTree();
470
-
471
- // Update statistics
472
- this.updateStatistics();
473
- }
474
-
475
- /**
476
- * Hide the file change viewer
477
- */
478
- hide() {
479
- this.modal.classList.remove('show');
480
- this.currentFile = null;
481
- }
482
-
483
- /**
484
- * Update from events
485
- */
486
- updateFromEvents() {
487
- if (window.eventViewer) {
488
- this.fileTracker.updateEvents(window.eventViewer.events);
489
- this.updateFileTree();
490
- this.updateStatistics();
491
- }
492
- }
493
-
494
- /**
495
- * Update session filter dropdown
496
- */
497
- updateSessionFilter() {
498
- const select = document.getElementById('file-session-filter');
499
- const sessions = Array.from(this.fileTracker.sessionData.keys());
500
-
501
- // Clear existing options except "All Sessions"
502
- select.innerHTML = '<option value="">All Sessions</option>';
503
-
504
- // Add session options
505
- sessions.forEach(sessionId => {
506
- const option = document.createElement('option');
507
- option.value = sessionId;
508
- option.textContent = `Session: ${sessionId.substring(0, 8)}...`;
509
- select.appendChild(option);
510
- });
511
-
512
- // Restore selection
513
- if (this.currentSessionId) {
514
- select.value = this.currentSessionId;
515
- }
516
- }
517
-
518
- /**
519
- * Update file tree display
520
- */
521
- updateFileTree() {
522
- const tree = this.fileTracker.getFileTree(this.currentSessionId);
523
-
524
- if (Object.keys(tree).length === 0) {
525
- this.treeContainer.innerHTML = `
526
- <div class="empty-state">
527
- <div class="empty-state-icon">📁</div>
528
- <div class="empty-state-text">No file changes detected</div>
529
- </div>
530
- `;
531
- return;
532
- }
533
-
534
- // Build tree HTML
535
- const treeHtml = Object.entries(tree)
536
- .sort((a, b) => b[1].totalOperations - a[1].totalOperations)
537
- .map(([dirPath, dirData]) => this.renderDirectoryGroup(dirPath, dirData))
538
- .join('');
539
-
540
- this.treeContainer.innerHTML = treeHtml;
541
-
542
- // Add event handlers
543
- this.attachTreeHandlers();
544
- }
545
-
546
- /**
547
- * Render a directory group
548
- * @param {string} dirPath - Directory path
549
- * @param {Object} dirData - Directory data
550
- * @returns {string} HTML
551
- */
552
- renderDirectoryGroup(dirPath, dirData) {
553
- const displayPath = dirPath === 'unknown' ? 'Unknown Directory' : dirPath;
554
-
555
- return `
556
- <div class="directory-group" data-path="${dirPath}">
557
- <div class="directory-header">
558
- <div class="directory-info">
559
- <span class="directory-icon"></span>
560
- <span class="directory-path">${this.escapeHtml(displayPath)}</span>
561
- </div>
562
- <div class="directory-stats">
563
- <span>${dirData.files.length} files</span>
564
- <span>${dirData.totalEdits} edits</span>
565
- <span>${dirData.totalWrites} writes</span>
566
- </div>
567
- </div>
568
- <div class="directory-files">
569
- ${dirData.files.map(file => this.renderFileItem(file)).join('')}
570
- </div>
571
- </div>
572
- `;
573
- }
574
-
575
- /**
576
- * Render a file item
577
- * @param {Object} fileData - File data
578
- * @returns {string} HTML
579
- */
580
- renderFileItem(fileData) {
581
- const badges = [];
582
- if (fileData.totalEdits > 0) {
583
- badges.push(`<span class="file-badge badge-edit">✏️ ${fileData.totalEdits}</span>`);
584
- }
585
- if (fileData.totalWrites > 0) {
586
- badges.push(`<span class="file-badge badge-write">💾 ${fileData.totalWrites}</span>`);
587
- }
588
- if (fileData.totalReads > 0 && fileData.totalEdits === 0 && fileData.totalWrites === 0) {
589
- badges.push(`<span class="file-badge badge-read">👁️ ${fileData.totalReads}</span>`);
590
- }
591
-
592
- const timestamp = new Date(fileData.lastModified).toLocaleTimeString();
593
-
594
- return `
595
- <div class="file-item" data-path="${fileData.path}">
596
- <div class="file-info">
597
- <span class="file-icon">📄</span>
598
- <span class="file-name">${this.escapeHtml(fileData.fileName)}</span>
599
- <div class="file-badges">${badges.join('')}</div>
600
- </div>
601
- <span class="file-timestamp">${timestamp}</span>
602
- </div>
603
- `;
604
- }
605
-
606
- /**
607
- * Attach tree event handlers
608
- */
609
- attachTreeHandlers() {
610
- // Directory headers - toggle expansion
611
- document.querySelectorAll('.directory-header').forEach(header => {
612
- header.addEventListener('click', (e) => {
613
- const group = header.closest('.directory-group');
614
- group.classList.toggle('expanded');
615
- });
616
- });
617
-
618
- // File items - show diff or content
619
- document.querySelectorAll('.file-item').forEach(item => {
620
- item.addEventListener('click', (e) => {
621
- e.stopPropagation();
622
- const filePath = item.dataset.path;
623
- this.showFileDetails(filePath);
624
- });
625
- });
626
-
627
- // Auto-expand first directory
628
- const firstDir = document.querySelector('.directory-group');
629
- if (firstDir) {
630
- firstDir.classList.add('expanded');
631
- }
632
- }
633
-
634
- /**
635
- * Show file details (diff or content)
636
- * @param {string} filePath - File path
637
- */
638
- showFileDetails(filePath) {
639
- const fileData = this.fileTracker.getFileDetails(filePath);
640
- if (!fileData) return;
641
-
642
- // If file has edits or writes, show diff
643
- if (fileData.totalEdits > 0 || fileData.totalWrites > 0) {
644
- const diffData = this.fileTracker.getFileDiff(filePath);
645
- if (diffData) {
646
- this.diffViewer.show(diffData);
647
- }
648
- } else {
649
- // For read-only files, could show content in a simple viewer
650
- console.log('Read-only file:', filePath);
651
- // Could implement a simple content viewer here
652
- }
653
- }
654
-
655
- /**
656
- * Update statistics
657
- */
658
- updateStatistics() {
659
- const stats = this.fileTracker.getStatistics();
660
-
661
- document.getElementById('total-files').textContent = stats.totalFiles;
662
- document.getElementById('total-edits').textContent =
663
- Array.from(this.fileTracker.fileChanges.values())
664
- .reduce((sum, f) => sum + f.totalEdits, 0);
665
- document.getElementById('total-writes').textContent =
666
- Array.from(this.fileTracker.fileChanges.values())
667
- .reduce((sum, f) => sum + f.totalWrites, 0);
668
- }
669
-
670
- /**
671
- * Escape HTML for safe display
672
- * @param {string} text - Text to escape
673
- * @returns {string} Escaped text
674
- */
675
- escapeHtml(text) {
676
- const div = document.createElement('div');
677
- div.textContent = text || '';
678
- return div.innerHTML;
679
- }
680
- }
681
-
682
- // Create singleton instance
683
- const fileChangeViewer = new FileChangeViewer();
684
-
685
- // Export for use in other modules
686
- if (typeof window !== 'undefined') {
687
- window.FileChangeViewer = fileChangeViewer;
688
- }
689
-
690
- export default fileChangeViewer;