claude-mpm 4.15.6__py3-none-any.whl → 4.21.3__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 (209) 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/PM_INSTRUCTIONS.md +49 -0
  5. claude_mpm/agents/agent_loader.py +4 -4
  6. claude_mpm/agents/templates/engineer.json +5 -1
  7. claude_mpm/agents/templates/php-engineer.json +10 -4
  8. claude_mpm/agents/templates/python_engineer.json +8 -3
  9. claude_mpm/agents/templates/rust_engineer.json +12 -7
  10. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  11. claude_mpm/cli/commands/__init__.py +2 -0
  12. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  13. claude_mpm/cli/commands/mpm_init/core.py +525 -0
  14. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  15. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  16. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  17. claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
  18. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  19. claude_mpm/cli/commands/mpm_init_handler.py +67 -1
  20. claude_mpm/cli/commands/skills.py +488 -0
  21. claude_mpm/cli/executor.py +2 -0
  22. claude_mpm/cli/parsers/base_parser.py +7 -0
  23. claude_mpm/cli/parsers/mpm_init_parser.py +42 -0
  24. claude_mpm/cli/parsers/skills_parser.py +137 -0
  25. claude_mpm/cli/startup.py +57 -0
  26. claude_mpm/commands/mpm-auto-configure.md +52 -0
  27. claude_mpm/commands/mpm-help.md +6 -0
  28. claude_mpm/commands/mpm-init.md +112 -6
  29. claude_mpm/commands/mpm-resume.md +372 -0
  30. claude_mpm/commands/mpm-version.md +113 -0
  31. claude_mpm/commands/mpm.md +2 -0
  32. claude_mpm/config/agent_config.py +2 -2
  33. claude_mpm/constants.py +12 -0
  34. claude_mpm/core/config.py +42 -0
  35. claude_mpm/core/factories.py +1 -1
  36. claude_mpm/core/interfaces.py +56 -1
  37. claude_mpm/core/optimized_agent_loader.py +3 -3
  38. claude_mpm/hooks/__init__.py +8 -0
  39. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  40. claude_mpm/hooks/session_resume_hook.py +121 -0
  41. claude_mpm/models/resume_log.py +340 -0
  42. claude_mpm/services/agents/auto_config_manager.py +1 -1
  43. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  44. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  45. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  46. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  47. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  48. claude_mpm/services/agents/local_template_manager.py +1 -1
  49. claude_mpm/services/agents/recommender.py +47 -0
  50. claude_mpm/services/cli/resume_service.py +617 -0
  51. claude_mpm/services/cli/session_manager.py +87 -0
  52. claude_mpm/services/cli/session_pause_manager.py +504 -0
  53. claude_mpm/services/cli/session_resume_helper.py +372 -0
  54. claude_mpm/services/core/base.py +26 -11
  55. claude_mpm/services/core/interfaces.py +56 -1
  56. claude_mpm/services/core/models/agent_config.py +3 -0
  57. claude_mpm/services/core/models/process.py +4 -0
  58. claude_mpm/services/core/path_resolver.py +1 -1
  59. claude_mpm/services/diagnostics/models.py +21 -0
  60. claude_mpm/services/event_bus/relay.py +23 -7
  61. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  62. claude_mpm/services/local_ops/__init__.py +2 -0
  63. claude_mpm/services/mcp_config_manager.py +7 -131
  64. claude_mpm/services/mcp_gateway/auto_configure.py +31 -25
  65. claude_mpm/services/mcp_gateway/core/process_pool.py +19 -10
  66. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +26 -21
  67. claude_mpm/services/memory/failure_tracker.py +19 -4
  68. claude_mpm/services/session_manager.py +205 -1
  69. claude_mpm/services/unified/deployment_strategies/local.py +1 -1
  70. claude_mpm/services/version_service.py +104 -1
  71. claude_mpm/skills/__init__.py +21 -0
  72. claude_mpm/skills/agent_skills_injector.py +324 -0
  73. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  74. claude_mpm/skills/bundled/api-documentation.md +393 -0
  75. claude_mpm/skills/bundled/async-testing.md +571 -0
  76. claude_mpm/skills/bundled/code-review.md +143 -0
  77. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  78. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  79. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  80. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  81. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  82. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  83. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  84. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  85. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  86. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  87. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  88. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  89. claude_mpm/skills/bundled/database-migration.md +199 -0
  90. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  91. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  92. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  93. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  94. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  95. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  96. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  97. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  98. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  99. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  100. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  101. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  102. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  103. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  104. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  105. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  106. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  107. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  108. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  109. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  110. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  111. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  112. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  113. claude_mpm/skills/bundled/git-workflow.md +414 -0
  114. claude_mpm/skills/bundled/imagemagick.md +204 -0
  115. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  116. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  117. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  118. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  119. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  120. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  121. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  122. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  123. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  124. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  125. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  126. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  127. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  128. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  129. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  130. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  131. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  132. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  133. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  134. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  135. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  136. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  137. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  138. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  139. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  140. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  141. claude_mpm/skills/bundled/pdf.md +141 -0
  142. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  143. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  144. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  145. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  146. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  147. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  148. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  149. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  150. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  151. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  152. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  153. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  154. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  155. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  156. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  157. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  158. claude_mpm/skills/bundled/security-scanning.md +327 -0
  159. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  160. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  161. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  162. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  163. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  164. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  165. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  166. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  167. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  168. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  169. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  170. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  171. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  172. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  173. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  174. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  175. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  176. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  177. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  178. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  179. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  180. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  181. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  182. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  183. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  184. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  185. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  186. claude_mpm/skills/bundled/xlsx.md +157 -0
  187. claude_mpm/skills/registry.py +97 -9
  188. claude_mpm/skills/skills_registry.py +348 -0
  189. claude_mpm/skills/skills_service.py +739 -0
  190. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  191. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  192. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  193. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  194. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  195. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  196. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  197. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  198. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  199. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  200. claude_mpm/utils/agent_dependency_loader.py +2 -2
  201. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/METADATA +211 -33
  202. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/RECORD +206 -64
  203. claude_mpm/agents/INSTRUCTIONS_OLD_DEPRECATED.md +0 -602
  204. claude_mpm/cli/commands/mpm_init.py +0 -2008
  205. claude_mpm/tools/code_tree_analyzer.py +0 -1825
  206. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/WHEEL +0 -0
  207. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/entry_points.txt +0 -0
  208. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/licenses/LICENSE +0 -0
  209. {claude_mpm-4.15.6.dist-info → claude_mpm-4.21.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Code Tree Analyzer Core
4
+ =======================
5
+
6
+ Main orchestrator that coordinates all code tree analysis operations.
7
+
8
+ WHY: Provides a unified interface for analyzing codebases with multiple
9
+ languages, handling caching and incremental processing.
10
+ """
11
+
12
+ import time
13
+ from pathlib import Path
14
+ from typing import Any, ClassVar, Dict, List, Optional
15
+
16
+ from ...core.logging_config import get_logger
17
+ from ..code_tree_events import CodeTreeEventEmitter
18
+ from .analysis import FileAnalyzer
19
+ from .cache import CacheManager
20
+ from .discovery import DiscoveryManager
21
+ from .events import EventManager
22
+ from .gitignore import GitignoreManager
23
+ from .models import CodeNode
24
+ from .multilang_analyzer import MultiLanguageAnalyzer
25
+ from .python_analyzer import PythonAnalyzer
26
+
27
+
28
+ class CodeTreeAnalyzer:
29
+ """Main analyzer that coordinates language-specific analyzers."""
30
+
31
+ # Define code file extensions at class level for directory filtering
32
+ CODE_EXTENSIONS: ClassVar[set] = {
33
+ ".py",
34
+ ".js",
35
+ ".jsx",
36
+ ".ts",
37
+ ".tsx",
38
+ ".mjs",
39
+ ".cjs",
40
+ ".java",
41
+ ".cpp",
42
+ ".c",
43
+ ".h",
44
+ ".hpp",
45
+ ".cs",
46
+ ".go",
47
+ ".rs",
48
+ ".rb",
49
+ ".php",
50
+ ".swift",
51
+ ".kt",
52
+ ".scala",
53
+ ".r",
54
+ ".m",
55
+ ".mm",
56
+ ".sh",
57
+ ".bash",
58
+ ".zsh",
59
+ ".fish",
60
+ ".ps1",
61
+ ".bat",
62
+ ".cmd",
63
+ ".sql",
64
+ ".html",
65
+ ".css",
66
+ ".scss",
67
+ ".sass",
68
+ ".less",
69
+ ".xml",
70
+ ".json",
71
+ ".yaml",
72
+ ".yml",
73
+ ".toml",
74
+ ".ini",
75
+ ".cfg",
76
+ ".conf",
77
+ ".md",
78
+ ".rst",
79
+ ".txt",
80
+ }
81
+
82
+ # File extensions to language mapping
83
+ LANGUAGE_MAP: ClassVar[dict] = {
84
+ ".py": "python",
85
+ ".js": "javascript",
86
+ ".jsx": "javascript",
87
+ ".ts": "typescript",
88
+ ".tsx": "typescript",
89
+ ".mjs": "javascript",
90
+ ".cjs": "javascript",
91
+ }
92
+
93
+ def __init__(
94
+ self,
95
+ emit_events: bool = True,
96
+ cache_dir: Optional[Path] = None,
97
+ emitter: Optional[CodeTreeEventEmitter] = None,
98
+ ):
99
+ """Initialize the code tree analyzer.
100
+
101
+ Args:
102
+ emit_events: Whether to emit Socket.IO events
103
+ cache_dir: Directory for caching analysis results
104
+ emitter: Optional event emitter to use (creates one if not provided)
105
+ """
106
+ self.logger = get_logger(__name__)
107
+ self.emit_events = emit_events
108
+ self.cache_dir = cache_dir or Path.home() / ".claude-mpm" / "code-cache"
109
+
110
+ # Use provided emitter or create one
111
+ if emitter:
112
+ self.emitter = emitter
113
+ elif emit_events:
114
+ self.emitter = CodeTreeEventEmitter(use_stdout=True)
115
+ else:
116
+ self.emitter = None
117
+
118
+ # Initialize managers
119
+ self.gitignore_manager = GitignoreManager()
120
+ self.cache_manager = CacheManager(self.cache_dir)
121
+ self.event_manager = EventManager(self.emitter)
122
+
123
+ # Initialize language analyzers
124
+ self.python_analyzer = PythonAnalyzer(self.emitter)
125
+ self.multi_lang_analyzer = MultiLanguageAnalyzer(self.emitter)
126
+
127
+ # For JavaScript/TypeScript
128
+ self.javascript_analyzer = self.multi_lang_analyzer
129
+ self.generic_analyzer = self.multi_lang_analyzer
130
+
131
+ # Initialize discovery and file analysis managers
132
+ self.discovery_manager = DiscoveryManager(self.gitignore_manager, self.emitter)
133
+ self.file_analyzer = FileAnalyzer(
134
+ self.python_analyzer,
135
+ self.multi_lang_analyzer,
136
+ self.cache_manager,
137
+ self.event_manager,
138
+ )
139
+
140
+ # Load cache
141
+ self.cache_manager.load()
142
+
143
+ def analyze_directory(
144
+ self,
145
+ directory: Path,
146
+ languages: Optional[List[str]] = None,
147
+ ignore_patterns: Optional[List[str]] = None,
148
+ max_depth: Optional[int] = None,
149
+ ) -> Dict[str, Any]:
150
+ """Analyze a directory and build code tree.
151
+
152
+ Args:
153
+ directory: Directory to analyze
154
+ languages: Languages to include (None for all)
155
+ ignore_patterns: Patterns to ignore
156
+ max_depth: Maximum directory depth
157
+
158
+ Returns:
159
+ Dictionary containing the code tree and statistics
160
+ """
161
+ if self.emitter:
162
+ self.emitter.start()
163
+
164
+ start_time = time.time()
165
+ all_nodes = []
166
+ files_processed = 0
167
+ total_files = 0
168
+
169
+ # Collect files to process
170
+ files_to_process = []
171
+ for ext, lang in self.LANGUAGE_MAP.items():
172
+ if languages and lang not in languages:
173
+ continue
174
+
175
+ for file_path in directory.rglob(f"*{ext}"):
176
+ # Use gitignore manager for filtering with directory as working dir
177
+ if self.gitignore_manager.should_ignore(file_path, directory):
178
+ continue
179
+
180
+ # Also check additional patterns
181
+ if ignore_patterns and any(
182
+ p in str(file_path) for p in ignore_patterns
183
+ ):
184
+ continue
185
+
186
+ # Check max depth
187
+ if max_depth:
188
+ depth = len(file_path.relative_to(directory).parts) - 1
189
+ if depth > max_depth:
190
+ continue
191
+
192
+ files_to_process.append((file_path, lang))
193
+
194
+ total_files = len(files_to_process)
195
+
196
+ # Process files
197
+ for file_path, language in files_to_process:
198
+ # Check cache
199
+ cache_key = self.cache_manager.get_cache_key(file_path)
200
+
201
+ if cached_nodes := self.cache_manager.get(cache_key):
202
+ nodes = cached_nodes
203
+ self.logger.debug(f"Using cached results for {file_path}")
204
+ else:
205
+ # Emit file start event
206
+ if self.emitter:
207
+ self.emitter.emit_file_start(str(file_path), language)
208
+
209
+ file_start = time.time()
210
+
211
+ # Analyze based on language
212
+ if language == "python":
213
+ nodes = self.python_analyzer.analyze_file(file_path)
214
+ else:
215
+ nodes = self.multi_lang_analyzer.analyze_file(file_path, language)
216
+
217
+ # If no nodes found and we have a valid language, emit basic file info
218
+ if not nodes and language != "unknown":
219
+ self.logger.debug(
220
+ f"No AST nodes found for {file_path}, using basic discovery"
221
+ )
222
+
223
+ # Cache results
224
+ self.cache_manager.set(cache_key, nodes)
225
+
226
+ # Emit file complete event
227
+ if self.emitter:
228
+ self.emitter.emit_file_complete(
229
+ str(file_path), len(nodes), time.time() - file_start
230
+ )
231
+
232
+ all_nodes.extend(nodes)
233
+ files_processed += 1
234
+
235
+ # Emit progress
236
+ if self.emitter and files_processed % 10 == 0:
237
+ self.emitter.emit_progress(
238
+ files_processed, total_files, f"Processing {file_path.name}"
239
+ )
240
+
241
+ # Build tree structure
242
+ tree = self._build_tree(all_nodes, directory)
243
+
244
+ # Calculate statistics
245
+ duration = time.time() - start_time
246
+ stats = {
247
+ "files_processed": files_processed,
248
+ "total_nodes": len(all_nodes),
249
+ "duration": duration,
250
+ "classes": sum(1 for n in all_nodes if n.node_type == "class"),
251
+ "functions": sum(
252
+ 1 for n in all_nodes if n.node_type in ("function", "method")
253
+ ),
254
+ "imports": sum(1 for n in all_nodes if n.node_type == "import"),
255
+ "languages": list(
256
+ {n.language for n in all_nodes if hasattr(n, "language")}
257
+ ),
258
+ "avg_complexity": (
259
+ sum(n.complexity for n in all_nodes) / len(all_nodes)
260
+ if all_nodes
261
+ else 0
262
+ ),
263
+ }
264
+
265
+ # Save cache
266
+ self.cache_manager.save()
267
+
268
+ # Stop emitter
269
+ if self.emitter:
270
+ self.emitter.stop()
271
+
272
+ return {"tree": tree, "nodes": all_nodes, "stats": stats}
273
+
274
+ def _build_tree(self, nodes: List[CodeNode], root_dir: Path) -> Dict[str, Any]:
275
+ """Build hierarchical tree structure from flat nodes list."""
276
+ tree = {
277
+ "name": root_dir.name,
278
+ "type": "directory",
279
+ "path": str(root_dir),
280
+ "children": [],
281
+ }
282
+
283
+ # Group nodes by file
284
+ files_map = {}
285
+ for node in nodes:
286
+ if node.file_path not in files_map:
287
+ files_map[node.file_path] = {
288
+ "name": Path(node.file_path).name,
289
+ "type": "file",
290
+ "path": node.file_path,
291
+ "children": [],
292
+ }
293
+
294
+ # Add node to file
295
+ node_dict = {
296
+ "name": node.name,
297
+ "type": node.node_type,
298
+ "line_start": node.line_start,
299
+ "line_end": node.line_end,
300
+ "complexity": node.complexity,
301
+ "has_docstring": node.has_docstring,
302
+ "decorators": node.decorators,
303
+ "signature": node.signature,
304
+ }
305
+ files_map[node.file_path]["children"].append(node_dict)
306
+
307
+ # Build directory structure
308
+ for file_path, file_node in files_map.items():
309
+ rel_path = Path(file_path).relative_to(root_dir)
310
+ parts = rel_path.parts
311
+
312
+ current = tree
313
+ for part in parts[:-1]:
314
+ # Find or create directory
315
+ dir_node = None
316
+ for child in current["children"]:
317
+ if child["type"] == "directory" and child["name"] == part:
318
+ dir_node = child
319
+ break
320
+
321
+ if not dir_node:
322
+ dir_node = {"name": part, "type": "directory", "children": []}
323
+ current["children"].append(dir_node)
324
+
325
+ current = dir_node
326
+
327
+ # Add file to current directory
328
+ current["children"].append(file_node)
329
+
330
+ return tree
331
+
332
+ def discover_top_level(
333
+ self, directory: Path, ignore_patterns: Optional[List[str]] = None
334
+ ) -> Dict[str, Any]:
335
+ """Discover only top-level directories and files for lazy loading.
336
+
337
+ Args:
338
+ directory: Root directory to discover
339
+ ignore_patterns: Patterns to ignore
340
+
341
+ Returns:
342
+ Dictionary with top-level structure
343
+ """
344
+ return self.discovery_manager.discover_top_level(directory, ignore_patterns)
345
+
346
+ def discover_directory(
347
+ self, dir_path: str, ignore_patterns: Optional[List[str]] = None
348
+ ) -> Dict[str, Any]:
349
+ """Discover contents of a specific directory for lazy loading.
350
+
351
+ Args:
352
+ dir_path: Directory path to discover
353
+ ignore_patterns: Patterns to ignore
354
+
355
+ Returns:
356
+ Dictionary with directory contents
357
+ """
358
+ return self.discovery_manager.discover_directory(dir_path, ignore_patterns)
359
+
360
+ def analyze_file(self, file_path: str) -> Dict[str, Any]:
361
+ """Analyze a specific file and return its AST structure.
362
+
363
+ Args:
364
+ file_path: Path to file to analyze
365
+
366
+ Returns:
367
+ Dictionary with file analysis results
368
+ """
369
+ return self.file_analyzer.analyze_file(file_path)
370
+
371
+ @property
372
+ def supported_extensions(self):
373
+ """Get list of supported file extensions."""
374
+ return {".py", ".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs"}
375
+
376
+ # Backward compatibility: Expose cache property
377
+ @property
378
+ def cache(self):
379
+ """Get cache dictionary for backward compatibility."""
380
+ return self.cache_manager.cache