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,443 +0,0 @@
1
- /**
2
- * File Change Tracker Module
3
- *
4
- * Tracks all file operations (Edit, Write, Read, MultiEdit) from event history
5
- * and builds a tree structure grouped by working directory.
6
- * Supports session-based filtering and stores complete edit history with timestamps.
7
- *
8
- * Architecture:
9
- * - Maintains a hierarchical structure of file changes
10
- * - Tracks file lifecycle (create, edit, delete)
11
- * - Provides session-aware filtering
12
- * - Stores complete history for diff generation
13
- */
14
- class FileChangeTracker {
15
- constructor() {
16
- // Main data structures
17
- this.fileChanges = new Map(); // Map<filePath, FileChangeData>
18
- this.sessionData = new Map(); // Map<sessionId, Set<filePath>>
19
- this.workingDirectories = new Map(); // Map<workingDir, Set<filePath>>
20
-
21
- // Current state
22
- this.currentSessionId = null;
23
- this.events = [];
24
-
25
- // File operation types we track
26
- this.FILE_OPERATIONS = {
27
- READ: 'Read',
28
- WRITE: 'Write',
29
- EDIT: 'Edit',
30
- MULTI_EDIT: 'MultiEdit',
31
- DELETE: 'Delete',
32
- CREATE: 'Create'
33
- };
34
-
35
- // Initialize
36
- this.initialized = false;
37
- console.log('FileChangeTracker initialized');
38
- }
39
-
40
- /**
41
- * Initialize the tracker
42
- */
43
- initialize() {
44
- if (this.initialized) return;
45
- this.initialized = true;
46
- console.log('FileChangeTracker ready');
47
- }
48
-
49
- /**
50
- * Process an event and extract file operations
51
- * @param {Object} event - Event data
52
- */
53
- processEvent(event) {
54
- // Check if this is a file-related tool event
55
- if (!this.isFileOperation(event)) return;
56
-
57
- const fileOp = this.extractFileOperation(event);
58
- if (!fileOp) return;
59
-
60
- // Add to our tracking structures
61
- this.addFileOperation(fileOp);
62
- }
63
-
64
- /**
65
- * Check if an event is a file operation
66
- * @param {Object} event - Event to check
67
- * @returns {boolean}
68
- */
69
- isFileOperation(event) {
70
- // Check for tool events with file operations
71
- if (event.type === 'tool' || event.subtype === 'pre_tool' || event.subtype === 'post_tool') {
72
- const toolName = event.tool_name || (event.data && event.data.tool_name);
73
- return Object.values(this.FILE_OPERATIONS).includes(toolName);
74
- }
75
-
76
- // Check for hook events with file operations
77
- if (event.type === 'hook' && event.data) {
78
- const toolName = event.data.tool_name;
79
- return Object.values(this.FILE_OPERATIONS).includes(toolName);
80
- }
81
-
82
- return false;
83
- }
84
-
85
- /**
86
- * Extract file operation details from an event
87
- * @param {Object} event - Event to process
88
- * @returns {Object|null} File operation data
89
- */
90
- extractFileOperation(event) {
91
- const toolName = event.tool_name || (event.data && event.data.tool_name);
92
- const params = event.tool_parameters || (event.data && event.data.tool_parameters) || {};
93
- const result = event.tool_result || (event.data && event.data.tool_result);
94
-
95
- // Extract file path based on tool type
96
- let filePath = null;
97
- let operation = toolName;
98
- let content = null;
99
- let oldContent = null;
100
-
101
- switch (toolName) {
102
- case this.FILE_OPERATIONS.READ:
103
- filePath = params.file_path;
104
- content = result && result.content;
105
- break;
106
-
107
- case this.FILE_OPERATIONS.WRITE:
108
- filePath = params.file_path;
109
- content = params.content;
110
- break;
111
-
112
- case this.FILE_OPERATIONS.EDIT:
113
- filePath = params.file_path;
114
- oldContent = params.old_string;
115
- content = params.new_string;
116
- break;
117
-
118
- case this.FILE_OPERATIONS.MULTI_EDIT:
119
- filePath = params.file_path;
120
- // For MultiEdit, we track each edit
121
- const edits = params.edits || [];
122
- return {
123
- filePath,
124
- operation,
125
- timestamp: event.timestamp,
126
- sessionId: event.session_id || 'unknown',
127
- workingDirectory: this.extractWorkingDirectory(event),
128
- edits: edits.map(edit => ({
129
- oldContent: edit.old_string,
130
- newContent: edit.new_string,
131
- replaceAll: edit.replace_all || false
132
- })),
133
- isMultiEdit: true,
134
- success: event.subtype === 'post_tool' && result && result.success !== false
135
- };
136
-
137
- default:
138
- return null;
139
- }
140
-
141
- if (!filePath) return null;
142
-
143
- return {
144
- filePath,
145
- operation,
146
- timestamp: event.timestamp,
147
- sessionId: event.session_id || 'unknown',
148
- workingDirectory: this.extractWorkingDirectory(event),
149
- content,
150
- oldContent,
151
- isEdit: operation === this.FILE_OPERATIONS.EDIT,
152
- isWrite: operation === this.FILE_OPERATIONS.WRITE,
153
- isRead: operation === this.FILE_OPERATIONS.READ,
154
- success: event.subtype === 'post_tool' && result && result.success !== false
155
- };
156
- }
157
-
158
- /**
159
- * Extract working directory from event
160
- * @param {Object} event - Event data
161
- * @returns {string} Working directory path
162
- */
163
- extractWorkingDirectory(event) {
164
- // Try to extract from event data
165
- if (event.data && event.data.working_directory) {
166
- return event.data.working_directory;
167
- }
168
-
169
- // Try to extract from context
170
- if (event.context && event.context.working_directory) {
171
- return event.context.working_directory;
172
- }
173
-
174
- // Try to extract from file path (get parent directory)
175
- const filePath = event.tool_parameters?.file_path ||
176
- (event.data && event.data.tool_parameters?.file_path);
177
- if (filePath) {
178
- const parts = filePath.split('/');
179
- parts.pop(); // Remove filename
180
- return parts.join('/') || '/';
181
- }
182
-
183
- return 'unknown';
184
- }
185
-
186
- /**
187
- * Add a file operation to our tracking structures
188
- * @param {Object} fileOp - File operation data
189
- */
190
- addFileOperation(fileOp) {
191
- const { filePath, sessionId, workingDirectory } = fileOp;
192
-
193
- // Initialize file change data if needed
194
- if (!this.fileChanges.has(filePath)) {
195
- this.fileChanges.set(filePath, {
196
- path: filePath,
197
- fileName: this.getFileName(filePath),
198
- workingDirectory,
199
- sessions: new Set(),
200
- operations: [],
201
- firstSeen: fileOp.timestamp,
202
- lastModified: fileOp.timestamp,
203
- currentContent: null,
204
- initialContent: null,
205
- totalEdits: 0,
206
- totalReads: 0,
207
- totalWrites: 0
208
- });
209
- }
210
-
211
- const fileData = this.fileChanges.get(filePath);
212
-
213
- // Update session tracking
214
- fileData.sessions.add(sessionId);
215
- if (!this.sessionData.has(sessionId)) {
216
- this.sessionData.set(sessionId, new Set());
217
- }
218
- this.sessionData.get(sessionId).add(filePath);
219
-
220
- // Update working directory tracking
221
- if (!this.workingDirectories.has(workingDirectory)) {
222
- this.workingDirectories.set(workingDirectory, new Set());
223
- }
224
- this.workingDirectories.get(workingDirectory).add(filePath);
225
-
226
- // Add operation to history
227
- fileData.operations.push(fileOp);
228
- fileData.lastModified = fileOp.timestamp;
229
-
230
- // Update content tracking
231
- if (fileOp.isRead && fileOp.content && !fileData.initialContent) {
232
- fileData.initialContent = fileOp.content;
233
- fileData.currentContent = fileOp.content;
234
- fileData.totalReads++;
235
- } else if (fileOp.isWrite) {
236
- if (!fileData.initialContent) {
237
- fileData.initialContent = '';
238
- }
239
- fileData.currentContent = fileOp.content;
240
- fileData.totalWrites++;
241
- } else if (fileOp.isEdit) {
242
- // Apply edit to current content
243
- if (fileData.currentContent && fileOp.oldContent) {
244
- fileData.currentContent = fileData.currentContent.replace(
245
- fileOp.oldContent,
246
- fileOp.content || ''
247
- );
248
- }
249
- fileData.totalEdits++;
250
- } else if (fileOp.isMultiEdit && fileOp.edits) {
251
- // Apply multiple edits
252
- let content = fileData.currentContent || '';
253
- for (const edit of fileOp.edits) {
254
- if (edit.replaceAll) {
255
- content = content.replaceAll(edit.oldContent, edit.newContent);
256
- } else {
257
- content = content.replace(edit.oldContent, edit.newContent);
258
- }
259
- }
260
- fileData.currentContent = content;
261
- fileData.totalEdits += fileOp.edits.length;
262
- }
263
- }
264
-
265
- /**
266
- * Get file name from path
267
- * @param {string} filePath - Full file path
268
- * @returns {string} File name
269
- */
270
- getFileName(filePath) {
271
- const parts = filePath.split('/');
272
- return parts[parts.length - 1] || filePath;
273
- }
274
-
275
- /**
276
- * Update with new events
277
- * @param {Array} events - Array of events
278
- */
279
- updateEvents(events) {
280
- // Clear and rebuild
281
- this.clear();
282
- this.events = events;
283
-
284
- // Process all events
285
- for (const event of events) {
286
- this.processEvent(event);
287
- }
288
-
289
- console.log(`FileChangeTracker updated: ${this.fileChanges.size} files tracked`);
290
- }
291
-
292
- /**
293
- * Get files for current session
294
- * @param {string} sessionId - Session ID to filter by
295
- * @returns {Array} Array of file change data
296
- */
297
- getFilesForSession(sessionId) {
298
- if (!sessionId) {
299
- return Array.from(this.fileChanges.values());
300
- }
301
-
302
- const sessionFiles = this.sessionData.get(sessionId);
303
- if (!sessionFiles) return [];
304
-
305
- return Array.from(sessionFiles).map(filePath =>
306
- this.fileChanges.get(filePath)
307
- ).filter(Boolean);
308
- }
309
-
310
- /**
311
- * Get file tree structure grouped by working directory
312
- * @param {string} sessionId - Optional session filter
313
- * @returns {Object} Tree structure
314
- */
315
- getFileTree(sessionId = null) {
316
- const files = this.getFilesForSession(sessionId);
317
- const tree = {};
318
-
319
- for (const fileData of files) {
320
- const wd = fileData.workingDirectory || 'unknown';
321
- if (!tree[wd]) {
322
- tree[wd] = {
323
- path: wd,
324
- name: this.getDirectoryName(wd),
325
- files: [],
326
- totalOperations: 0,
327
- totalEdits: 0,
328
- totalReads: 0,
329
- totalWrites: 0
330
- };
331
- }
332
-
333
- tree[wd].files.push(fileData);
334
- tree[wd].totalOperations += fileData.operations.length;
335
- tree[wd].totalEdits += fileData.totalEdits;
336
- tree[wd].totalReads += fileData.totalReads;
337
- tree[wd].totalWrites += fileData.totalWrites;
338
- }
339
-
340
- // Sort files within each directory
341
- Object.values(tree).forEach(dir => {
342
- dir.files.sort((a, b) =>
343
- new Date(b.lastModified) - new Date(a.lastModified)
344
- );
345
- });
346
-
347
- return tree;
348
- }
349
-
350
- /**
351
- * Get directory name from path
352
- * @param {string} dirPath - Directory path
353
- * @returns {string} Directory name
354
- */
355
- getDirectoryName(dirPath) {
356
- if (dirPath === 'unknown') return 'Unknown Directory';
357
- const parts = dirPath.split('/');
358
- return parts[parts.length - 1] || dirPath;
359
- }
360
-
361
- /**
362
- * Get file change details
363
- * @param {string} filePath - File path
364
- * @returns {Object|null} File change data
365
- */
366
- getFileDetails(filePath) {
367
- return this.fileChanges.get(filePath) || null;
368
- }
369
-
370
- /**
371
- * Get operations for a file
372
- * @param {string} filePath - File path
373
- * @param {string} sessionId - Optional session filter
374
- * @returns {Array} Array of operations
375
- */
376
- getFileOperations(filePath, sessionId = null) {
377
- const fileData = this.fileChanges.get(filePath);
378
- if (!fileData) return [];
379
-
380
- let operations = fileData.operations;
381
- if (sessionId) {
382
- operations = operations.filter(op => op.sessionId === sessionId);
383
- }
384
-
385
- return operations.sort((a, b) =>
386
- new Date(a.timestamp) - new Date(b.timestamp)
387
- );
388
- }
389
-
390
- /**
391
- * Get diff data for a file
392
- * @param {string} filePath - File path
393
- * @returns {Object} Diff data with initial and current content
394
- */
395
- getFileDiff(filePath) {
396
- const fileData = this.fileChanges.get(filePath);
397
- if (!fileData) return null;
398
-
399
- return {
400
- filePath,
401
- fileName: fileData.fileName,
402
- initialContent: fileData.initialContent || '',
403
- currentContent: fileData.currentContent || '',
404
- hasChanges: fileData.initialContent !== fileData.currentContent,
405
- operations: fileData.operations,
406
- totalEdits: fileData.totalEdits,
407
- totalWrites: fileData.totalWrites
408
- };
409
- }
410
-
411
- /**
412
- * Clear all tracked data
413
- */
414
- clear() {
415
- this.fileChanges.clear();
416
- this.sessionData.clear();
417
- this.workingDirectories.clear();
418
- this.events = [];
419
- }
420
-
421
- /**
422
- * Get statistics
423
- * @returns {Object} Statistics
424
- */
425
- getStatistics() {
426
- return {
427
- totalFiles: this.fileChanges.size,
428
- totalSessions: this.sessionData.size,
429
- totalDirectories: this.workingDirectories.size,
430
- filesWithEdits: Array.from(this.fileChanges.values())
431
- .filter(f => f.totalEdits > 0).length,
432
- filesWithWrites: Array.from(this.fileChanges.values())
433
- .filter(f => f.totalWrites > 0).length,
434
- readOnlyFiles: Array.from(this.fileChanges.values())
435
- .filter(f => f.totalEdits === 0 && f.totalWrites === 0).length
436
- };
437
- }
438
- }
439
-
440
- // Export for use in other modules
441
- if (typeof window !== 'undefined') {
442
- window.FileChangeTracker = FileChangeTracker;
443
- }