claude-mpm 3.9.11__py3-none-any.whl → 4.0.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.
Files changed (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -1,864 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Project Analyzer Service
4
- =======================
5
-
6
- Analyzes project characteristics to enable project-specific memory creation.
7
-
8
- WHY: Instead of creating generic memories, agents need to understand the specific
9
- project they're working on - its tech stack, architecture patterns, coding conventions,
10
- and key components. This service extracts these characteristics automatically.
11
-
12
- DESIGN DECISION: Separates project analysis from memory creation to allow reuse
13
- across different memory-related services and enable caching of analysis results.
14
-
15
- This service analyzes:
16
- - Technology stack from config files (package.json, requirements.txt, etc.)
17
- - Code patterns from source files
18
- - Architecture patterns from directory structure
19
- - Testing frameworks and approaches
20
- - API patterns and endpoints
21
- - Database integrations
22
- - Project-specific terminology and conventions
23
- """
24
-
25
- import json
26
- import re
27
- from pathlib import Path
28
- from typing import Dict, List, Optional, Any, Set, Tuple
29
- import logging
30
- from dataclasses import dataclass, asdict
31
- from collections import defaultdict, Counter
32
-
33
- from claude_mpm.core.config import Config
34
- from claude_mpm.utils.paths import PathResolver
35
- from claude_mpm.core.interfaces import ProjectAnalyzerInterface
36
-
37
-
38
- @dataclass
39
- class ProjectCharacteristics:
40
- """Structured representation of project characteristics."""
41
-
42
- # Core project info
43
- project_name: str
44
- primary_language: Optional[str]
45
- languages: List[str]
46
- frameworks: List[str]
47
-
48
- # Architecture and structure
49
- architecture_type: str
50
- main_modules: List[str]
51
- key_directories: List[str]
52
- entry_points: List[str]
53
-
54
- # Development practices
55
- testing_framework: Optional[str]
56
- test_patterns: List[str]
57
- package_manager: Optional[str]
58
- build_tools: List[str]
59
-
60
- # Integrations and dependencies
61
- databases: List[str]
62
- web_frameworks: List[str]
63
- api_patterns: List[str]
64
- key_dependencies: List[str]
65
-
66
- # Project-specific patterns
67
- code_conventions: List[str]
68
- configuration_patterns: List[str]
69
- project_terminology: List[str]
70
-
71
- # Documentation and structure
72
- documentation_files: List[str]
73
- important_configs: List[str]
74
-
75
- def to_dict(self) -> Dict[str, Any]:
76
- """Convert to dictionary for JSON serialization."""
77
- return asdict(self)
78
-
79
-
80
- class ProjectAnalyzer(ProjectAnalyzerInterface):
81
- """Analyzes project characteristics for context-aware memory creation.
82
-
83
- WHY: Generic agent memories aren't helpful for specific projects. This analyzer
84
- extracts project-specific characteristics that enable agents to create relevant,
85
- actionable memories with proper context.
86
-
87
- DESIGN DECISION: Uses a combination of file pattern analysis, content parsing,
88
- and directory structure analysis to build comprehensive project understanding
89
- without requiring external tools or API calls.
90
- """
91
-
92
- # Common configuration files and their indicators
93
- CONFIG_FILE_PATTERNS = {
94
- 'package.json': 'node_js',
95
- 'requirements.txt': 'python',
96
- 'pyproject.toml': 'python',
97
- 'setup.py': 'python',
98
- 'Cargo.toml': 'rust',
99
- 'pom.xml': 'java',
100
- 'build.gradle': 'java',
101
- 'composer.json': 'php',
102
- 'Gemfile': 'ruby',
103
- 'go.mod': 'go',
104
- 'CMakeLists.txt': 'cpp',
105
- 'Makefile': 'c_cpp',
106
- }
107
-
108
- # Framework detection patterns
109
- FRAMEWORK_PATTERNS = {
110
- 'flask': ['from flask', 'Flask(', 'app.route'],
111
- 'django': ['from django', 'DJANGO_SETTINGS', 'django.contrib'],
112
- 'fastapi': ['from fastapi', 'FastAPI(', '@app.'],
113
- 'express': ['express()', 'app.get(', 'app.post('],
114
- 'react': ['import React', 'from react', 'ReactDOM'],
115
- 'vue': ['Vue.createApp', 'new Vue(', 'vue-'],
116
- 'angular': ['@Component', '@Injectable', 'Angular'],
117
- 'spring': ['@SpringBootApplication', '@RestController', 'Spring'],
118
- 'rails': ['Rails.application', 'ApplicationController'],
119
- }
120
-
121
- # Database detection patterns
122
- DATABASE_PATTERNS = {
123
- 'postgresql': ['psycopg2', 'postgresql:', 'postgres:', 'pg_'],
124
- 'mysql': ['mysql-connector', 'mysql:', 'MySQLdb'],
125
- 'sqlite': ['sqlite3', 'sqlite:', '.db', '.sqlite'],
126
- 'mongodb': ['pymongo', 'mongodb:', 'mongoose'],
127
- 'redis': ['redis:', 'redis-py', 'RedisClient'],
128
- 'elasticsearch': ['elasticsearch:', 'elastic'],
129
- }
130
-
131
- def __init__(self, config: Optional[Config] = None, working_directory: Optional[Path] = None):
132
- """Initialize the project analyzer.
133
-
134
- Args:
135
- config: Optional Config object
136
- working_directory: Optional working directory path. If not provided, uses current.
137
- """
138
- self.config = config or Config()
139
- self.working_directory = working_directory or PathResolver.get_project_root()
140
- self.logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
141
-
142
- # Cache for analysis results
143
- self._analysis_cache: Optional[ProjectCharacteristics] = None
144
- self._cache_timestamp: Optional[float] = None
145
-
146
- def analyze_project(self, force_refresh: bool = False) -> ProjectCharacteristics:
147
- """Analyze the current project and return characteristics.
148
-
149
- WHY: Comprehensive project analysis enables agents to create memories
150
- that are specific to the actual project context, tech stack, and patterns.
151
-
152
- Args:
153
- force_refresh: If True, ignores cache and performs fresh analysis
154
-
155
- Returns:
156
- ProjectCharacteristics: Structured project analysis results
157
- """
158
- try:
159
- # Check cache first (unless force refresh)
160
- if not force_refresh and self._analysis_cache and self._cache_timestamp:
161
- # Cache is valid for 5 minutes
162
- import time
163
- if time.time() - self._cache_timestamp < 300:
164
- self.logger.debug("Using cached project analysis")
165
- return self._analysis_cache
166
-
167
- self.logger.info(f"Analyzing project at: {self.working_directory}")
168
-
169
- # Initialize characteristics with basic info
170
- characteristics = ProjectCharacteristics(
171
- project_name=self.working_directory.name,
172
- primary_language=None,
173
- languages=[],
174
- frameworks=[],
175
- architecture_type="unknown",
176
- main_modules=[],
177
- key_directories=[],
178
- entry_points=[],
179
- testing_framework=None,
180
- test_patterns=[],
181
- package_manager=None,
182
- build_tools=[],
183
- databases=[],
184
- web_frameworks=[],
185
- api_patterns=[],
186
- key_dependencies=[],
187
- code_conventions=[],
188
- configuration_patterns=[],
189
- project_terminology=[],
190
- documentation_files=[],
191
- important_configs=[]
192
- )
193
-
194
- # Perform various analyses
195
- self._analyze_config_files(characteristics)
196
- self._analyze_directory_structure(characteristics)
197
- self._analyze_source_code(characteristics)
198
- self._analyze_dependencies(characteristics)
199
- self._analyze_testing_patterns(characteristics)
200
- self._analyze_documentation(characteristics)
201
- self._infer_architecture_type(characteristics)
202
- self._extract_project_terminology(characteristics)
203
-
204
- # Cache the results
205
- self._analysis_cache = characteristics
206
- import time
207
- self._cache_timestamp = time.time()
208
-
209
- self.logger.info(f"Project analysis complete: {characteristics.primary_language} project with {len(characteristics.frameworks)} frameworks")
210
- return characteristics
211
-
212
- except Exception as e:
213
- self.logger.error(f"Error analyzing project: {e}")
214
- # Return minimal characteristics on error
215
- return ProjectCharacteristics(
216
- project_name=self.working_directory.name,
217
- primary_language="unknown",
218
- languages=[],
219
- frameworks=[],
220
- architecture_type="unknown",
221
- main_modules=[],
222
- key_directories=[],
223
- entry_points=[],
224
- testing_framework=None,
225
- test_patterns=[],
226
- package_manager=None,
227
- build_tools=[],
228
- databases=[],
229
- web_frameworks=[],
230
- api_patterns=[],
231
- key_dependencies=[],
232
- code_conventions=[],
233
- configuration_patterns=[],
234
- project_terminology=[],
235
- documentation_files=[],
236
- important_configs=[]
237
- )
238
-
239
- def _analyze_config_files(self, characteristics: ProjectCharacteristics) -> None:
240
- """Analyze configuration files to determine tech stack.
241
-
242
- WHY: Configuration files are the most reliable indicators of project
243
- technology stack and dependencies. They provide definitive information
244
- about what technologies are actually used.
245
-
246
- Args:
247
- characteristics: ProjectCharacteristics object to update
248
- """
249
- config_files = []
250
- languages_found = set()
251
-
252
- for config_file, language in self.CONFIG_FILE_PATTERNS.items():
253
- config_path = self.working_directory / config_file
254
- if config_path.exists():
255
- config_files.append(config_file)
256
- languages_found.add(language)
257
- characteristics.important_configs.append(str(config_path.relative_to(self.working_directory)))
258
-
259
- # Parse specific config files for more details
260
- try:
261
- if config_file == 'package.json':
262
- self._parse_package_json(config_path, characteristics)
263
- elif config_file in ['requirements.txt', 'pyproject.toml']:
264
- self._parse_python_dependencies(config_path, characteristics)
265
- elif config_file == 'Cargo.toml':
266
- self._parse_cargo_toml(config_path, characteristics)
267
- except Exception as e:
268
- self.logger.warning(f"Error parsing {config_file}: {e}")
269
-
270
- # Set primary language (prefer more specific indicators)
271
- language_priority = ['python', 'node_js', 'rust', 'java', 'go', 'php', 'ruby']
272
- for lang in language_priority:
273
- if lang in languages_found:
274
- characteristics.primary_language = lang
275
- break
276
-
277
- characteristics.languages = list(languages_found)
278
-
279
- # Determine package manager
280
- if 'package.json' in config_files:
281
- if (self.working_directory / 'yarn.lock').exists():
282
- characteristics.package_manager = 'yarn'
283
- elif (self.working_directory / 'pnpm-lock.yaml').exists():
284
- characteristics.package_manager = 'pnpm'
285
- else:
286
- characteristics.package_manager = 'npm'
287
- elif 'requirements.txt' in config_files or 'pyproject.toml' in config_files:
288
- characteristics.package_manager = 'pip'
289
- elif 'Cargo.toml' in config_files:
290
- characteristics.package_manager = 'cargo'
291
-
292
- def _parse_package_json(self, package_path: Path, characteristics: ProjectCharacteristics) -> None:
293
- """Parse package.json for Node.js project details."""
294
- try:
295
- with open(package_path, 'r') as f:
296
- package_data = json.load(f)
297
-
298
- # Extract dependencies
299
- all_deps = {}
300
- all_deps.update(package_data.get('dependencies', {}))
301
- all_deps.update(package_data.get('devDependencies', {}))
302
-
303
- # Identify frameworks and tools
304
- for dep_name in all_deps.keys():
305
- dep_lower = dep_name.lower()
306
-
307
- # Web frameworks
308
- if any(fw in dep_lower for fw in ['express', 'koa', 'hapi']):
309
- characteristics.web_frameworks.append(dep_name)
310
- elif any(fw in dep_lower for fw in ['react', 'vue', 'angular', 'svelte']):
311
- characteristics.frameworks.append(dep_name)
312
- elif any(db in dep_lower for db in ['mysql', 'postgres', 'mongodb', 'redis']):
313
- characteristics.databases.append(dep_name)
314
- elif any(test in dep_lower for test in ['jest', 'mocha', 'cypress', 'playwright']):
315
- if not characteristics.testing_framework:
316
- characteristics.testing_framework = dep_name
317
-
318
- characteristics.key_dependencies.append(dep_name)
319
-
320
- # Check scripts for build tools
321
- scripts = package_data.get('scripts', {})
322
- for script_name, script_cmd in scripts.items():
323
- if any(tool in script_cmd for tool in ['webpack', 'rollup', 'vite', 'parcel']):
324
- characteristics.build_tools.append(script_name)
325
-
326
- except Exception as e:
327
- self.logger.warning(f"Error parsing package.json: {e}")
328
-
329
- def _parse_python_dependencies(self, deps_path: Path, characteristics: ProjectCharacteristics) -> None:
330
- """Parse Python dependency files."""
331
- try:
332
- if deps_path.name == 'requirements.txt':
333
- content = deps_path.read_text()
334
- deps = [line.strip().split('=')[0].split('>')[0].split('<')[0]
335
- for line in content.splitlines()
336
- if line.strip() and not line.startswith('#')]
337
- elif deps_path.name == 'pyproject.toml':
338
- try:
339
- import tomllib
340
- except ImportError:
341
- try:
342
- import tomli as tomllib
343
- except ImportError:
344
- self.logger.warning(f"TOML parsing not available for {deps_path}")
345
- return
346
- with open(deps_path, 'rb') as f:
347
- data = tomllib.load(f)
348
- deps = list(data.get('project', {}).get('dependencies', []))
349
- deps.extend(list(data.get('tool', {}).get('poetry', {}).get('dependencies', {}).keys()))
350
- else:
351
- return
352
-
353
- # Identify frameworks and tools
354
- for dep in deps:
355
- dep_lower = dep.lower()
356
-
357
- # Web frameworks
358
- if dep_lower in ['flask', 'django', 'fastapi', 'tornado']:
359
- characteristics.web_frameworks.append(dep)
360
- elif dep_lower in ['pytest', 'unittest2', 'nose']:
361
- if not characteristics.testing_framework:
362
- characteristics.testing_framework = dep
363
- elif any(db in dep_lower for db in ['psycopg2', 'mysql', 'sqlite', 'redis', 'mongo']):
364
- characteristics.databases.append(dep)
365
-
366
- characteristics.key_dependencies.append(dep)
367
-
368
- except Exception as e:
369
- self.logger.warning(f"Error parsing Python dependencies: {e}")
370
-
371
- def _parse_cargo_toml(self, cargo_path: Path, characteristics: ProjectCharacteristics) -> None:
372
- """Parse Cargo.toml for Rust project details."""
373
- try:
374
- try:
375
- import tomllib
376
- except ImportError:
377
- try:
378
- import tomli as tomllib
379
- except ImportError:
380
- self.logger.warning(f"TOML parsing not available for {cargo_path}")
381
- return
382
- with open(cargo_path, 'rb') as f:
383
- cargo_data = tomllib.load(f)
384
-
385
- deps = cargo_data.get('dependencies', {})
386
- for dep_name in deps.keys():
387
- characteristics.key_dependencies.append(dep_name)
388
-
389
- # Identify common Rust frameworks
390
- if dep_name in ['actix-web', 'warp', 'rocket']:
391
- characteristics.web_frameworks.append(dep_name)
392
- elif dep_name in ['tokio', 'async-std']:
393
- characteristics.frameworks.append(dep_name)
394
-
395
- except Exception as e:
396
- self.logger.warning(f"Error parsing Cargo.toml: {e}")
397
-
398
- def _analyze_directory_structure(self, characteristics: ProjectCharacteristics) -> None:
399
- """Analyze directory structure for architecture patterns.
400
-
401
- WHY: Directory structure reveals architectural decisions and project
402
- organization patterns that agents should understand and follow.
403
-
404
- Args:
405
- characteristics: ProjectCharacteristics object to update
406
- """
407
- # Common important directories to look for
408
- important_dirs = [
409
- 'src', 'lib', 'app', 'components', 'services', 'models', 'views',
410
- 'controllers', 'routes', 'api', 'web', 'static', 'templates',
411
- 'tests', 'test', '__tests__', 'spec', 'docs', 'documentation',
412
- 'config', 'configs', 'settings', 'utils', 'helpers', 'core',
413
- 'modules', 'packages', 'plugins', 'extensions'
414
- ]
415
-
416
- # Check which directories exist
417
- existing_dirs = []
418
- for dir_name in important_dirs:
419
- dir_path = self.working_directory / dir_name
420
- if dir_path.exists() and dir_path.is_dir():
421
- existing_dirs.append(dir_name)
422
-
423
- # Special handling for certain directories
424
- if dir_name in ['src', 'lib', 'app']:
425
- # These are likely main module directories
426
- characteristics.main_modules.extend(self._get_subdirectories(dir_path))
427
-
428
- characteristics.key_directories = existing_dirs
429
-
430
- # Look for entry points
431
- entry_point_patterns = [
432
- 'main.py', 'app.py', 'server.py', 'index.js', 'main.js',
433
- 'app.js', 'server.js', 'main.rs', 'lib.rs', 'Main.java',
434
- 'main.go', 'index.php', 'application.rb'
435
- ]
436
-
437
- for pattern in entry_point_patterns:
438
- entry_path = self.working_directory / pattern
439
- if entry_path.exists():
440
- characteristics.entry_points.append(pattern)
441
-
442
- # Also check in src/ directory
443
- src_entry_path = self.working_directory / 'src' / pattern
444
- if src_entry_path.exists():
445
- characteristics.entry_points.append(f'src/{pattern}')
446
-
447
- def _get_subdirectories(self, path: Path, max_depth: int = 2) -> List[str]:
448
- """Get subdirectory names up to a certain depth."""
449
- subdirs = []
450
- try:
451
- for item in path.iterdir():
452
- if item.is_dir() and not item.name.startswith('.'):
453
- subdirs.append(item.name)
454
- if max_depth > 1:
455
- for subitem in item.iterdir():
456
- if subitem.is_dir() and not subitem.name.startswith('.'):
457
- subdirs.append(f"{item.name}/{subitem.name}")
458
- except PermissionError:
459
- pass
460
- return subdirs[:10] # Limit to prevent overwhelming output
461
-
462
- def _analyze_source_code(self, characteristics: ProjectCharacteristics) -> None:
463
- """Analyze source code files for patterns and conventions.
464
-
465
- WHY: Source code contains the actual implementation patterns that agents
466
- should understand and follow. This analysis extracts coding conventions
467
- and architectural patterns from the codebase.
468
-
469
- Args:
470
- characteristics: ProjectCharacteristics object to update
471
- """
472
- source_extensions = {
473
- '.py': 'python',
474
- '.js': 'javascript',
475
- '.ts': 'typescript',
476
- '.jsx': 'react',
477
- '.tsx': 'react',
478
- '.rs': 'rust',
479
- '.java': 'java',
480
- '.go': 'go',
481
- '.php': 'php',
482
- '.rb': 'ruby',
483
- '.cpp': 'cpp',
484
- '.cc': 'cpp',
485
- '.c': 'c'
486
- }
487
-
488
- # Find source files
489
- source_files = []
490
- languages_found = set()
491
-
492
- for ext, lang in source_extensions.items():
493
- files = list(self.working_directory.rglob(f'*{ext}'))
494
- # Filter out node_modules, .git, etc.
495
- files = [f for f in files if not any(part.startswith('.') or part == 'node_modules'
496
- for part in f.parts)]
497
- source_files.extend(files)
498
- if files:
499
- languages_found.add(lang)
500
-
501
- # Update languages found
502
- characteristics.languages.extend([lang for lang in languages_found
503
- if lang not in characteristics.languages])
504
-
505
- # Analyze a sample of source files for patterns
506
- sample_files = source_files[:20] # Don't analyze too many files
507
-
508
- framework_mentions = Counter()
509
- pattern_mentions = Counter()
510
-
511
- for file_path in sample_files:
512
- try:
513
- content = file_path.read_text(encoding='utf-8', errors='ignore')
514
-
515
- # Look for framework patterns
516
- for framework, patterns in self.FRAMEWORK_PATTERNS.items():
517
- if any(pattern in content for pattern in patterns):
518
- framework_mentions[framework] += 1
519
-
520
- # Look for database patterns
521
- for db, patterns in self.DATABASE_PATTERNS.items():
522
- if any(pattern in content for pattern in patterns):
523
- if db not in characteristics.databases:
524
- characteristics.databases.append(db)
525
-
526
- # Look for common patterns
527
- if 'class ' in content and 'def __init__' in content:
528
- pattern_mentions['object_oriented'] += 1
529
- if '@app.route' in content or 'app.get(' in content:
530
- pattern_mentions['web_routes'] += 1
531
- if 'async def' in content or 'async function' in content:
532
- pattern_mentions['async_programming'] += 1
533
- if 'import pytest' in content or 'describe(' in content:
534
- pattern_mentions['unit_testing'] += 1
535
-
536
- except Exception as e:
537
- self.logger.debug(f"Error analyzing {file_path}: {e}")
538
- continue
539
-
540
- # Add discovered frameworks
541
- for framework, count in framework_mentions.most_common(5):
542
- if framework not in characteristics.frameworks:
543
- characteristics.frameworks.append(framework)
544
-
545
- # Add coding conventions based on patterns found
546
- for pattern, count in pattern_mentions.most_common():
547
- if count >= 2: # Pattern appears in multiple files
548
- characteristics.code_conventions.append(pattern.replace('_', ' ').title())
549
-
550
- def _analyze_dependencies(self, characteristics: ProjectCharacteristics) -> None:
551
- """Analyze dependencies for integration patterns.
552
-
553
- Args:
554
- characteristics: ProjectCharacteristics object to update
555
- """
556
- # This is partially covered by config file analysis
557
- # Here we can add more sophisticated dependency analysis
558
-
559
- # Look for common integration patterns in dependencies
560
- api_indicators = [
561
- 'requests', 'axios', 'fetch', 'http', 'urllib',
562
- 'rest', 'graphql', 'grpc', 'soap'
563
- ]
564
-
565
- for dep in characteristics.key_dependencies:
566
- dep_lower = dep.lower()
567
- for indicator in api_indicators:
568
- if indicator in dep_lower:
569
- if 'REST API' not in characteristics.api_patterns:
570
- characteristics.api_patterns.append('REST API')
571
- break
572
-
573
- def _analyze_testing_patterns(self, characteristics: ProjectCharacteristics) -> None:
574
- """Analyze testing patterns and frameworks.
575
-
576
- Args:
577
- characteristics: ProjectCharacteristics object to update
578
- """
579
- test_dirs = ['tests', 'test', '__tests__', 'spec']
580
- test_patterns = []
581
-
582
- for test_dir in test_dirs:
583
- test_path = self.working_directory / test_dir
584
- if test_path.exists() and test_path.is_dir():
585
- test_patterns.append(f"Tests in /{test_dir}/ directory")
586
-
587
- # Look for test files to understand patterns
588
- test_files = list(test_path.rglob('*.py')) + list(test_path.rglob('*.js')) + list(test_path.rglob('*.ts'))
589
-
590
- for test_file in test_files[:5]: # Sample a few test files
591
- try:
592
- content = test_file.read_text(encoding='utf-8', errors='ignore')
593
-
594
- if 'def test_' in content:
595
- test_patterns.append("Python unittest pattern")
596
- if 'describe(' in content and 'it(' in content:
597
- test_patterns.append("BDD test pattern")
598
- if '@pytest.fixture' in content:
599
- test_patterns.append("pytest fixtures")
600
- if 'beforeEach(' in content or 'beforeAll(' in content:
601
- test_patterns.append("Setup/teardown patterns")
602
-
603
- except Exception:
604
- continue
605
-
606
- characteristics.test_patterns = list(set(test_patterns))
607
-
608
- def _analyze_documentation(self, characteristics: ProjectCharacteristics) -> None:
609
- """Analyze documentation files.
610
-
611
- Args:
612
- characteristics: ProjectCharacteristics object to update
613
- """
614
- doc_patterns = [
615
- 'README.md', 'README.rst', 'README.txt',
616
- 'CONTRIBUTING.md', 'CHANGELOG.md', 'HISTORY.md',
617
- 'docs/', 'documentation/', 'wiki/'
618
- ]
619
-
620
- doc_files = []
621
- for pattern in doc_patterns:
622
- doc_path = self.working_directory / pattern
623
- if doc_path.exists():
624
- if doc_path.is_file():
625
- doc_files.append(pattern)
626
- elif doc_path.is_dir():
627
- # Find markdown files in doc directories
628
- md_files = list(doc_path.rglob('*.md'))[:10]
629
- doc_files.extend([str(f.relative_to(self.working_directory)) for f in md_files])
630
-
631
- characteristics.documentation_files = doc_files
632
-
633
- def _infer_architecture_type(self, characteristics: ProjectCharacteristics) -> None:
634
- """Infer architecture type based on discovered patterns.
635
-
636
- Args:
637
- characteristics: ProjectCharacteristics object to update
638
- """
639
- # Simple architecture inference based on patterns
640
- if any(fw in characteristics.web_frameworks for fw in ['flask', 'django', 'express', 'fastapi']):
641
- if 'api' in characteristics.key_directories:
642
- characteristics.architecture_type = "REST API Service"
643
- else:
644
- characteristics.architecture_type = "Web Application"
645
- elif 'services' in characteristics.key_directories:
646
- characteristics.architecture_type = "Service-Oriented Architecture"
647
- elif 'modules' in characteristics.key_directories or 'packages' in characteristics.key_directories:
648
- characteristics.architecture_type = "Modular Architecture"
649
- elif characteristics.primary_language == 'python' and 'cli' in characteristics.main_modules:
650
- characteristics.architecture_type = "CLI Application"
651
- elif any('react' in fw.lower() for fw in characteristics.frameworks):
652
- characteristics.architecture_type = "Single Page Application"
653
- else:
654
- characteristics.architecture_type = "Standard Application"
655
-
656
- def _extract_project_terminology(self, characteristics: ProjectCharacteristics) -> None:
657
- """Extract project-specific terminology from various sources.
658
-
659
- WHY: Projects often have domain-specific terminology that agents should
660
- understand and use consistently.
661
-
662
- Args:
663
- characteristics: ProjectCharacteristics object to update
664
- """
665
- terminology = set()
666
-
667
- # Extract from project name
668
- project_words = re.findall(r'[A-Z][a-z]+|[a-z]+', characteristics.project_name)
669
- terminology.update(project_words)
670
-
671
- # Extract from directory names
672
- for dir_name in characteristics.key_directories:
673
- words = re.findall(r'[A-Z][a-z]+|[a-z]+', dir_name)
674
- terminology.update(words)
675
-
676
- # Extract from main modules
677
- for module in characteristics.main_modules:
678
- words = re.findall(r'[A-Z][a-z]+|[a-z]+', module)
679
- terminology.update(words)
680
-
681
- # Filter out common words and keep domain-specific terms
682
- common_words = {
683
- 'src', 'lib', 'app', 'main', 'test', 'tests', 'docs', 'config',
684
- 'utils', 'helpers', 'core', 'base', 'common', 'shared', 'public',
685
- 'private', 'static', 'assets', 'build', 'dist', 'node', 'modules'
686
- }
687
-
688
- domain_terms = [term for term in terminology
689
- if len(term) > 3 and term.lower() not in common_words]
690
-
691
- characteristics.project_terminology = list(set(domain_terms))[:10] # Limit to most relevant
692
-
693
- def get_project_context_summary(self) -> str:
694
- """Get a concise summary of project context for memory templates.
695
-
696
- WHY: Provides a formatted summary specifically designed for inclusion
697
- in agent memory templates, focusing on the most relevant characteristics.
698
-
699
- Returns:
700
- str: Formatted project context summary
701
- """
702
- characteristics = self.analyze_project()
703
-
704
- summary_parts = []
705
-
706
- # Basic project info
707
- lang_info = characteristics.primary_language or "mixed"
708
- if characteristics.languages and len(characteristics.languages) > 1:
709
- lang_info = f"{lang_info} (with {', '.join(characteristics.languages[1:3])})"
710
-
711
- summary_parts.append(f"{characteristics.project_name}: {lang_info} {characteristics.architecture_type.lower()}")
712
-
713
- # Key directories and modules
714
- if characteristics.main_modules:
715
- modules_str = ", ".join(characteristics.main_modules[:4])
716
- summary_parts.append(f"- Main modules: {modules_str}")
717
-
718
- # Frameworks and tools
719
- if characteristics.frameworks or characteristics.web_frameworks:
720
- all_frameworks = characteristics.frameworks + characteristics.web_frameworks
721
- frameworks_str = ", ".join(all_frameworks[:3])
722
- summary_parts.append(f"- Uses: {frameworks_str}")
723
-
724
- # Testing
725
- if characteristics.testing_framework:
726
- summary_parts.append(f"- Testing: {characteristics.testing_framework}")
727
- elif characteristics.test_patterns:
728
- summary_parts.append(f"- Testing: {characteristics.test_patterns[0]}")
729
-
730
- # Key patterns
731
- if characteristics.code_conventions:
732
- patterns_str = ", ".join(characteristics.code_conventions[:2])
733
- summary_parts.append(f"- Key patterns: {patterns_str}")
734
-
735
- return "\n".join(summary_parts)
736
-
737
- def get_important_files_for_context(self) -> List[str]:
738
- """Get list of important files that should be considered for memory context.
739
-
740
- WHY: Instead of hardcoding which files to analyze for memory creation,
741
- this method dynamically determines the most relevant files based on
742
- the actual project structure.
743
-
744
- Returns:
745
- List[str]: List of file paths relative to project root
746
- """
747
- characteristics = self.analyze_project()
748
- important_files = []
749
-
750
- # Always include standard documentation
751
- standard_docs = ['README.md', 'CONTRIBUTING.md', 'CHANGELOG.md']
752
- for doc in standard_docs:
753
- if (self.working_directory / doc).exists():
754
- important_files.append(doc)
755
-
756
- # Include configuration files
757
- important_files.extend(characteristics.important_configs)
758
-
759
- # Include project-specific documentation
760
- important_files.extend(characteristics.documentation_files[:5])
761
-
762
- # Include entry points
763
- important_files.extend(characteristics.entry_points)
764
-
765
- # Look for architecture documentation
766
- arch_patterns = ['ARCHITECTURE.md', 'docs/architecture.md', 'docs/STRUCTURE.md']
767
- for pattern in arch_patterns:
768
- if (self.working_directory / pattern).exists():
769
- important_files.append(pattern)
770
-
771
- # Remove duplicates and return
772
- return list(set(important_files))
773
-
774
- # ================================================================================
775
- # Interface Adapter Methods
776
- # ================================================================================
777
- # These methods adapt the existing implementation to comply with ProjectAnalyzerInterface
778
-
779
- def detect_technology_stack(self) -> List[str]:
780
- """Detect technologies used in the project.
781
-
782
- WHY: This adapter method provides interface compliance by extracting
783
- technology information from the analyzed project characteristics.
784
-
785
- Returns:
786
- List of detected technologies
787
- """
788
- characteristics = self.analyze_project()
789
-
790
- technologies = []
791
- technologies.extend(characteristics.languages)
792
- technologies.extend(characteristics.frameworks)
793
- technologies.extend(characteristics.web_frameworks)
794
- technologies.extend(characteristics.databases)
795
-
796
- # Add package manager as technology
797
- if characteristics.package_manager:
798
- technologies.append(characteristics.package_manager)
799
-
800
- # Add build tools
801
- technologies.extend(characteristics.build_tools)
802
-
803
- # Remove duplicates
804
- return list(set(technologies))
805
-
806
- def analyze_code_patterns(self) -> Dict[str, Any]:
807
- """Analyze code patterns and conventions.
808
-
809
- WHY: This adapter method provides interface compliance by extracting
810
- pattern information from the project characteristics.
811
-
812
- Returns:
813
- Dictionary of pattern analysis results
814
- """
815
- characteristics = self.analyze_project()
816
-
817
- return {
818
- "code_conventions": characteristics.code_conventions,
819
- "test_patterns": characteristics.test_patterns,
820
- "api_patterns": characteristics.api_patterns,
821
- "configuration_patterns": characteristics.configuration_patterns,
822
- "architecture_type": characteristics.architecture_type
823
- }
824
-
825
- def get_project_structure(self) -> Dict[str, Any]:
826
- """Get project directory structure analysis.
827
-
828
- WHY: This adapter method provides interface compliance by organizing
829
- structural information from the project characteristics.
830
-
831
- Returns:
832
- Dictionary representing project structure
833
- """
834
- characteristics = self.analyze_project()
835
-
836
- return {
837
- "project_name": characteristics.project_name,
838
- "main_modules": characteristics.main_modules,
839
- "key_directories": characteristics.key_directories,
840
- "entry_points": characteristics.entry_points,
841
- "documentation_files": characteristics.documentation_files,
842
- "important_configs": characteristics.important_configs,
843
- "architecture_type": characteristics.architecture_type
844
- }
845
-
846
- def identify_entry_points(self) -> List[Path]:
847
- """Identify project entry points.
848
-
849
- WHY: This adapter method provides interface compliance by converting
850
- string entry points to Path objects as expected by the interface.
851
-
852
- Returns:
853
- List of entry point paths
854
- """
855
- characteristics = self.analyze_project()
856
-
857
- # Convert string paths to Path objects
858
- entry_paths = []
859
- for entry_point in characteristics.entry_points:
860
- entry_path = self.working_directory / entry_point
861
- if entry_path.exists():
862
- entry_paths.append(entry_path)
863
-
864
- return entry_paths