claude-mpm 3.4.27__py3-none-any.whl → 3.5.0__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.
Files changed (123) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +182 -299
  3. claude_mpm/agents/agent_loader.py +283 -57
  4. claude_mpm/agents/agent_loader_integration.py +6 -9
  5. claude_mpm/agents/base_agent.json +2 -1
  6. claude_mpm/agents/base_agent_loader.py +1 -1
  7. claude_mpm/cli/__init__.py +5 -7
  8. claude_mpm/cli/commands/__init__.py +0 -2
  9. claude_mpm/cli/commands/agents.py +1 -1
  10. claude_mpm/cli/commands/memory.py +1 -1
  11. claude_mpm/cli/commands/run.py +12 -0
  12. claude_mpm/cli/parser.py +0 -13
  13. claude_mpm/cli/utils.py +1 -1
  14. claude_mpm/config/__init__.py +44 -2
  15. claude_mpm/config/agent_config.py +348 -0
  16. claude_mpm/config/paths.py +322 -0
  17. claude_mpm/constants.py +0 -1
  18. claude_mpm/core/__init__.py +2 -5
  19. claude_mpm/core/agent_registry.py +63 -17
  20. claude_mpm/core/claude_runner.py +354 -43
  21. claude_mpm/core/config.py +7 -1
  22. claude_mpm/core/config_aliases.py +4 -3
  23. claude_mpm/core/config_paths.py +151 -0
  24. claude_mpm/core/factories.py +4 -50
  25. claude_mpm/core/logger.py +11 -13
  26. claude_mpm/core/service_registry.py +2 -2
  27. claude_mpm/dashboard/static/js/components/agent-inference.js +101 -25
  28. claude_mpm/dashboard/static/js/components/event-processor.js +3 -2
  29. claude_mpm/hooks/claude_hooks/hook_handler.py +343 -83
  30. claude_mpm/hooks/memory_integration_hook.py +1 -1
  31. claude_mpm/init.py +37 -6
  32. claude_mpm/scripts/socketio_daemon.py +6 -2
  33. claude_mpm/services/__init__.py +71 -3
  34. claude_mpm/services/agents/__init__.py +85 -0
  35. claude_mpm/services/agents/deployment/__init__.py +21 -0
  36. claude_mpm/services/{agent_deployment.py → agents/deployment/agent_deployment.py} +192 -41
  37. claude_mpm/services/{agent_lifecycle_manager.py → agents/deployment/agent_lifecycle_manager.py} +11 -10
  38. claude_mpm/services/agents/loading/__init__.py +11 -0
  39. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +9 -8
  40. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +2 -2
  41. claude_mpm/services/{framework_agent_loader.py → agents/loading/framework_agent_loader.py} +116 -40
  42. claude_mpm/services/agents/management/__init__.py +9 -0
  43. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +6 -5
  44. claude_mpm/services/agents/memory/__init__.py +21 -0
  45. claude_mpm/services/{agent_memory_manager.py → agents/memory/agent_memory_manager.py} +3 -3
  46. claude_mpm/services/agents/registry/__init__.py +29 -0
  47. claude_mpm/services/{agent_registry.py → agents/registry/agent_registry.py} +101 -16
  48. claude_mpm/services/{deployed_agent_discovery.py → agents/registry/deployed_agent_discovery.py} +12 -2
  49. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +6 -5
  50. claude_mpm/services/async_session_logger.py +584 -0
  51. claude_mpm/services/claude_session_logger.py +299 -0
  52. claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
  53. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +17 -17
  54. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +3 -3
  55. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +1 -1
  56. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +1 -1
  57. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +19 -24
  58. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +1 -1
  59. claude_mpm/services/framework_claude_md_generator.py +4 -2
  60. claude_mpm/services/memory/__init__.py +17 -0
  61. claude_mpm/services/{memory_builder.py → memory/builder.py} +3 -3
  62. claude_mpm/services/memory/cache/__init__.py +14 -0
  63. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +1 -1
  64. claude_mpm/services/memory/cache/simple_cache.py +317 -0
  65. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +1 -1
  66. claude_mpm/services/{memory_router.py → memory/router.py} +1 -1
  67. claude_mpm/services/optimized_hook_service.py +542 -0
  68. claude_mpm/services/project_registry.py +14 -8
  69. claude_mpm/services/response_tracker.py +237 -0
  70. claude_mpm/services/ticketing_service_original.py +4 -2
  71. claude_mpm/services/version_control/branch_strategy.py +3 -1
  72. claude_mpm/utils/paths.py +12 -10
  73. claude_mpm/utils/session_logging.py +114 -0
  74. claude_mpm/validation/agent_validator.py +2 -1
  75. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
  76. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/RECORD +83 -106
  77. claude_mpm/cli/commands/ui.py +0 -57
  78. claude_mpm/core/simple_runner.py +0 -1046
  79. claude_mpm/hooks/builtin/__init__.py +0 -1
  80. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  81. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  82. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  83. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  84. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  85. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  86. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  87. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  88. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  89. claude_mpm/orchestration/__init__.py +0 -6
  90. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  91. claude_mpm/orchestration/archive/factory.py +0 -215
  92. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  93. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  94. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  95. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  96. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  97. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  98. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  99. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  100. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  101. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  102. claude_mpm/schemas/workflow_validator.py +0 -411
  103. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  104. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  105. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  106. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  107. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  108. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  109. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  110. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  111. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  112. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  113. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  114. claude_mpm/ui/__init__.py +0 -1
  115. claude_mpm/ui/rich_terminal_ui.py +0 -295
  116. claude_mpm/ui/terminal_ui.py +0 -328
  117. /claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +0 -0
  118. /claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +0 -0
  119. /claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +0 -0
  120. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
  121. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
  122. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
  123. {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
@@ -1,339 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Version Control Helper Module
4
- =============================
5
-
6
- This module provides version control utilities for the Parent Directory Manager.
7
- It handles git operations and version control integration for the framework.
8
-
9
- Key Features:
10
- - Git repository detection
11
- - Branch management helpers
12
- - Commit status checking
13
- - Version control integration utilities
14
- """
15
-
16
- import os
17
- from pathlib import Path
18
- from typing import Optional, List, Dict, Tuple, Any
19
- import logging
20
- from claude_pm.utils.subprocess_manager import SubprocessManager
21
-
22
-
23
- class VersionControlHelper:
24
- """
25
- Helper class for version control operations.
26
-
27
- This class provides utilities for interacting with git repositories
28
- and managing version control operations within the framework.
29
- """
30
-
31
- def __init__(self, working_dir: Path, logger: Optional[logging.Logger] = None):
32
- """
33
- Initialize the Version Control Helper.
34
-
35
- Args:
36
- working_dir: The working directory path
37
- logger: Optional logger instance
38
- """
39
- self.working_dir = Path(working_dir)
40
- self.logger = logger or logging.getLogger(__name__)
41
-
42
- # Initialize subprocess manager
43
- self.subprocess_manager = SubprocessManager()
44
-
45
- # Cache git repository detection
46
- self._is_git_repo: Optional[bool] = None
47
- self._git_root: Optional[Path] = None
48
-
49
- def is_git_repository(self) -> bool:
50
- """
51
- Check if the working directory is inside a git repository.
52
-
53
- Returns:
54
- True if inside a git repository, False otherwise
55
- """
56
- if self._is_git_repo is not None:
57
- return self._is_git_repo
58
-
59
- try:
60
- result = self.subprocess_manager.run(
61
- ["git", "rev-parse", "--git-dir"],
62
- cwd=self.working_dir,
63
- capture_output=True,
64
- text=True
65
- )
66
- self._is_git_repo = result.success
67
-
68
- if self._is_git_repo:
69
- # Get the root of the git repository
70
- root_result = self.subprocess_manager.run(
71
- ["git", "rev-parse", "--show-toplevel"],
72
- cwd=self.working_dir,
73
- capture_output=True,
74
- text=True
75
- )
76
- if root_result.success:
77
- self._git_root = Path(root_result.stdout.strip())
78
-
79
- return self._is_git_repo
80
- except (OSError, FileNotFoundError):
81
- self._is_git_repo = False
82
- return False
83
-
84
- def get_git_root(self) -> Optional[Path]:
85
- """
86
- Get the root directory of the git repository.
87
-
88
- Returns:
89
- Path to git root directory, or None if not in a git repo
90
- """
91
- if self.is_git_repository():
92
- return self._git_root
93
- return None
94
-
95
- def get_current_branch(self) -> Optional[str]:
96
- """
97
- Get the current git branch name.
98
-
99
- Returns:
100
- Branch name or None if not in a git repository
101
- """
102
- if not self.is_git_repository():
103
- return None
104
-
105
- try:
106
- result = self.subprocess_manager.run(
107
- ["git", "rev-parse", "--abbrev-ref", "HEAD"],
108
- cwd=self.working_dir,
109
- capture_output=True,
110
- text=True
111
- )
112
- if result.success:
113
- return result.stdout.strip()
114
- except Exception:
115
- pass
116
-
117
- return None
118
-
119
- def has_uncommitted_changes(self) -> bool:
120
- """
121
- Check if there are uncommitted changes in the repository.
122
-
123
- Returns:
124
- True if there are uncommitted changes, False otherwise
125
- """
126
- if not self.is_git_repository():
127
- return False
128
-
129
- try:
130
- result = self.subprocess_manager.run(
131
- ["git", "status", "--porcelain"],
132
- cwd=self.working_dir,
133
- capture_output=True,
134
- text=True
135
- )
136
- if result.success:
137
- return bool(result.stdout.strip())
138
- except Exception:
139
- pass
140
-
141
- return False
142
-
143
- def get_file_status(self, file_path: Path) -> Optional[str]:
144
- """
145
- Get the git status of a specific file.
146
-
147
- Args:
148
- file_path: Path to the file to check
149
-
150
- Returns:
151
- Git status string or None if not tracked
152
- """
153
- if not self.is_git_repository():
154
- return None
155
-
156
- try:
157
- # Make path relative to git root for consistent results
158
- git_root = self.get_git_root()
159
- if git_root:
160
- try:
161
- relative_path = file_path.relative_to(git_root)
162
- except ValueError:
163
- # File is outside git repository
164
- return None
165
- else:
166
- relative_path = file_path
167
-
168
- result = self.subprocess_manager.run(
169
- ["git", "status", "--porcelain", str(relative_path)],
170
- cwd=self.working_dir,
171
- capture_output=True,
172
- text=True
173
- )
174
- if result.success and result.stdout:
175
- return result.stdout.strip()
176
- except Exception:
177
- pass
178
-
179
- return None
180
-
181
- def is_file_ignored(self, file_path: Path) -> bool:
182
- """
183
- Check if a file is ignored by git.
184
-
185
- Args:
186
- file_path: Path to check
187
-
188
- Returns:
189
- True if file is ignored, False otherwise
190
- """
191
- if not self.is_git_repository():
192
- return False
193
-
194
- try:
195
- result = self.subprocess_manager.run(
196
- ["git", "check-ignore", str(file_path)],
197
- cwd=self.working_dir,
198
- capture_output=True
199
- )
200
- return result.success
201
- except Exception:
202
- return False
203
-
204
- def add_to_gitignore(self, pattern: str) -> bool:
205
- """
206
- Add a pattern to .gitignore file.
207
-
208
- Args:
209
- pattern: Pattern to add to gitignore
210
-
211
- Returns:
212
- True if successfully added, False otherwise
213
- """
214
- if not self.is_git_repository():
215
- self.logger.debug("Not in a git repository, skipping gitignore update")
216
- return False
217
-
218
- git_root = self.get_git_root()
219
- if not git_root:
220
- return False
221
-
222
- gitignore_path = git_root / ".gitignore"
223
-
224
- try:
225
- # Read existing content
226
- existing_patterns = set()
227
- if gitignore_path.exists():
228
- existing_patterns = set(gitignore_path.read_text().strip().split('\n'))
229
-
230
- # Add pattern if not already present
231
- if pattern not in existing_patterns:
232
- with open(gitignore_path, 'a') as f:
233
- if gitignore_path.exists() and gitignore_path.stat().st_size > 0:
234
- f.write('\n')
235
- f.write(f"{pattern}\n")
236
-
237
- self.logger.info(f"Added '{pattern}' to .gitignore")
238
- return True
239
- else:
240
- self.logger.debug(f"Pattern '{pattern}' already in .gitignore")
241
- return True
242
-
243
- except Exception as e:
244
- self.logger.warning(f"Failed to update .gitignore: {e}")
245
- return False
246
-
247
- def get_last_commit_info(self) -> Optional[Dict[str, str]]:
248
- """
249
- Get information about the last commit.
250
-
251
- Returns:
252
- Dictionary with commit info or None if not in a git repo
253
- """
254
- if not self.is_git_repository():
255
- return None
256
-
257
- try:
258
- # Get commit hash
259
- hash_result = self.subprocess_manager.run(
260
- ["git", "rev-parse", "HEAD"],
261
- cwd=self.working_dir,
262
- capture_output=True,
263
- text=True
264
- )
265
-
266
- # Get commit message
267
- msg_result = self.subprocess_manager.run(
268
- ["git", "log", "-1", "--pretty=%B"],
269
- cwd=self.working_dir,
270
- capture_output=True,
271
- text=True
272
- )
273
-
274
- # Get commit author
275
- author_result = self.subprocess_manager.run(
276
- ["git", "log", "-1", "--pretty=%an <%ae>"],
277
- cwd=self.working_dir,
278
- capture_output=True,
279
- text=True
280
- )
281
-
282
- # Get commit date
283
- date_result = self.subprocess_manager.run(
284
- ["git", "log", "-1", "--pretty=%ai"],
285
- cwd=self.working_dir,
286
- capture_output=True,
287
- text=True
288
- )
289
-
290
- if all(r.success for r in [hash_result, msg_result, author_result, date_result]):
291
- return {
292
- "hash": hash_result.stdout.strip(),
293
- "message": msg_result.stdout.strip(),
294
- "author": author_result.stdout.strip(),
295
- "date": date_result.stdout.strip()
296
- }
297
-
298
- except Exception:
299
- pass
300
-
301
- return None
302
-
303
- def create_version_tag(self, version: str, message: Optional[str] = None) -> bool:
304
- """
305
- Create a git tag for a version.
306
-
307
- Args:
308
- version: Version string (e.g., "v1.0.0")
309
- message: Optional tag message
310
-
311
- Returns:
312
- True if tag was created successfully
313
- """
314
- if not self.is_git_repository():
315
- return False
316
-
317
- try:
318
- if message:
319
- cmd = ["git", "tag", "-a", version, "-m", message]
320
- else:
321
- cmd = ["git", "tag", version]
322
-
323
- result = self.subprocess_manager.run(
324
- cmd,
325
- cwd=self.working_dir,
326
- capture_output=True,
327
- text=True
328
- )
329
-
330
- if result.success:
331
- self.logger.info(f"Created git tag: {version}")
332
- return True
333
- else:
334
- self.logger.warning(f"Failed to create git tag: {result.stderr}")
335
- return False
336
-
337
- except Exception as e:
338
- self.logger.warning(f"Error creating git tag: {e}")
339
- return False
@@ -1,222 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Version Manager - Handles subsystem version tracking and management
4
- ================================================================================
5
-
6
- This module manages subsystem version tracking, loading, updating, and reporting
7
- for the parent directory manager service.
8
- """
9
-
10
- from pathlib import Path
11
- from typing import Dict, Any, Optional
12
- from datetime import datetime
13
- import logging
14
- from ...utils.path_operations import path_ops
15
-
16
-
17
- class VersionManager:
18
- """Manages subsystem version tracking and operations."""
19
-
20
- def __init__(
21
- self,
22
- framework_path: Path,
23
- logger: Optional[logging.Logger] = None
24
- ):
25
- """
26
- Initialize the Version Manager.
27
-
28
- Args:
29
- framework_path: Path to framework
30
- logger: Logger instance to use
31
- """
32
- self.framework_path = framework_path
33
- self.logger = logger or logging.getLogger(__name__)
34
- self.subsystem_versions: Dict[str, Dict[str, Any]] = {}
35
-
36
- # Define subsystem version files
37
- self.subsystem_files = {
38
- "health": "HEALTH_VERSION"
39
- }
40
-
41
- async def load_subsystem_versions(self) -> None:
42
- """Load subsystem versions from version files."""
43
- try:
44
- for subsystem, filename in self.subsystem_files.items():
45
- version_file = self.framework_path / filename
46
- if path_ops.validate_exists(version_file):
47
- try:
48
- version_content = path_ops.safe_read(version_file)
49
- version = version_content.strip() if version_content else ""
50
- self.subsystem_versions[subsystem] = {
51
- "version": version,
52
- "file_path": str(version_file),
53
- "last_checked": datetime.now().isoformat()
54
- }
55
- self.logger.debug(f"Loaded {subsystem} version: {version}")
56
- except Exception as e:
57
- self.logger.error(f"Failed to read {subsystem} version from {version_file}: {e}")
58
- self.subsystem_versions[subsystem] = {
59
- "version": "unknown",
60
- "file_path": str(version_file),
61
- "error": str(e),
62
- "last_checked": datetime.now().isoformat()
63
- }
64
- else:
65
- self.logger.warning(f"Subsystem version file not found: {version_file}")
66
- self.subsystem_versions[subsystem] = {
67
- "version": "not_found",
68
- "file_path": str(version_file),
69
- "last_checked": datetime.now().isoformat()
70
- }
71
-
72
- self.logger.info(f"Loading subsystem versions...")
73
-
74
- except Exception as e:
75
- self.logger.error(f"Failed to load subsystem versions: {e}")
76
-
77
- def get_subsystem_versions(self) -> Dict[str, Any]:
78
- """
79
- Get all detected subsystem versions.
80
-
81
- Returns:
82
- Dictionary with subsystem version information
83
- """
84
- return {
85
- "framework_path": str(self.framework_path),
86
- "subsystems": self.subsystem_versions.copy(),
87
- "detection_timestamp": datetime.now().isoformat()
88
- }
89
-
90
- def get_subsystem_version(self, subsystem: str) -> Optional[str]:
91
- """
92
- Get version for a specific subsystem.
93
-
94
- Args:
95
- subsystem: Name of the subsystem
96
-
97
- Returns:
98
- Version string or None if not found
99
- """
100
- version_info = self.subsystem_versions.get(subsystem, {})
101
- version = version_info.get("version")
102
-
103
- # Return None for error states
104
- if version in ["unknown", "not_found"]:
105
- return None
106
-
107
- return version
108
-
109
- async def update_subsystem_version(
110
- self,
111
- subsystem: str,
112
- new_version: str,
113
- create_backup_func
114
- ) -> bool:
115
- """
116
- Update a subsystem version file.
117
-
118
- Args:
119
- subsystem: Name of the subsystem
120
- new_version: New version string
121
- create_backup_func: Function to create backup of version file
122
-
123
- Returns:
124
- True if updated successfully, False otherwise
125
- """
126
- try:
127
- filename = self.subsystem_files.get(subsystem)
128
- if not filename:
129
- self.logger.error(f"Unknown subsystem: {subsystem}")
130
- return False
131
-
132
- version_file = self.framework_path / filename
133
-
134
- # Backup existing version file if it exists
135
- if version_file.exists():
136
- backup_path = await create_backup_func(version_file)
137
- if backup_path:
138
- self.logger.info(f"Created backup of {filename}: {backup_path}")
139
-
140
- # Write new version
141
- version_file.write_text(new_version.strip())
142
-
143
- # Update in-memory tracking
144
- self.subsystem_versions[subsystem] = {
145
- "version": new_version,
146
- "file_path": str(version_file),
147
- "last_updated": datetime.now().isoformat()
148
- }
149
-
150
- self.logger.info(f"Updated {subsystem} version to: {new_version}")
151
- return True
152
-
153
- except Exception as e:
154
- self.logger.error(f"Failed to update {subsystem} version to {new_version}: {e}")
155
- return False
156
-
157
- def get_subsystem_version_report(self) -> Dict[str, Any]:
158
- """
159
- Generate a comprehensive subsystem version report.
160
-
161
- Returns:
162
- Dictionary with detailed version information
163
- """
164
- try:
165
- report = {
166
- "report_timestamp": datetime.now().isoformat(),
167
- "framework_path": str(self.framework_path),
168
- "subsystem_count": len(self.subsystem_versions),
169
- "subsystems": {},
170
- "summary": {
171
- "total": 0,
172
- "found": 0,
173
- "missing": 0,
174
- "errors": 0
175
- }
176
- }
177
-
178
- for subsystem, info in self.subsystem_versions.items():
179
- version = info.get("version", "unknown")
180
- status = "found"
181
-
182
- if version == "not_found":
183
- status = "missing"
184
- report["summary"]["missing"] += 1
185
- elif version == "unknown" or "error" in info:
186
- status = "error"
187
- report["summary"]["errors"] += 1
188
- else:
189
- report["summary"]["found"] += 1
190
-
191
- report["summary"]["total"] += 1
192
-
193
- report["subsystems"][subsystem] = {
194
- "version": version,
195
- "status": status,
196
- "file_path": info.get("file_path"),
197
- "last_checked": info.get("last_checked"),
198
- "error": info.get("error")
199
- }
200
-
201
- return report
202
-
203
- except Exception as e:
204
- self.logger.error(f"Failed to generate subsystem version report: {e}")
205
- return {
206
- "error": str(e),
207
- "report_timestamp": datetime.now().isoformat()
208
- }
209
-
210
- def get_version_report(self) -> Dict[str, Any]:
211
- """
212
- Get a simple version report (for compatibility with VersionControlHelper).
213
-
214
- Returns:
215
- Dictionary with subsystem versions
216
- """
217
- return {
218
- "subsystems": {
219
- subsystem: info.get("version", "unknown")
220
- for subsystem, info in self.subsystem_versions.items()
221
- }
222
- }
claude_mpm/ui/__init__.py DELETED
@@ -1 +0,0 @@
1
- """Terminal UI components for claude-mpm."""