claude-mpm 4.7.4__py3-none-any.whl → 4.18.2__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 (308) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
  3. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  4. claude_mpm/agents/BASE_PM.md +106 -1
  5. claude_mpm/agents/OUTPUT_STYLE.md +329 -11
  6. claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
  7. claude_mpm/agents/agent_loader.py +17 -5
  8. claude_mpm/agents/frontmatter_validator.py +284 -253
  9. claude_mpm/agents/templates/README.md +465 -0
  10. claude_mpm/agents/templates/agent-manager.json +4 -1
  11. claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
  12. claude_mpm/agents/templates/api_qa.json +11 -2
  13. claude_mpm/agents/templates/circuit_breakers.md +638 -0
  14. claude_mpm/agents/templates/clerk-ops.json +12 -2
  15. claude_mpm/agents/templates/code_analyzer.json +8 -2
  16. claude_mpm/agents/templates/content-agent.json +358 -0
  17. claude_mpm/agents/templates/dart_engineer.json +15 -2
  18. claude_mpm/agents/templates/data_engineer.json +15 -2
  19. claude_mpm/agents/templates/documentation.json +10 -2
  20. claude_mpm/agents/templates/engineer.json +21 -1
  21. claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
  22. claude_mpm/agents/templates/git_file_tracking.md +584 -0
  23. claude_mpm/agents/templates/golang_engineer.json +270 -0
  24. claude_mpm/agents/templates/imagemagick.json +4 -1
  25. claude_mpm/agents/templates/java_engineer.json +346 -0
  26. claude_mpm/agents/templates/local_ops_agent.json +1227 -6
  27. claude_mpm/agents/templates/memory_manager.json +4 -1
  28. claude_mpm/agents/templates/nextjs_engineer.json +141 -133
  29. claude_mpm/agents/templates/ops.json +12 -2
  30. claude_mpm/agents/templates/php-engineer.json +270 -174
  31. claude_mpm/agents/templates/pm_examples.md +474 -0
  32. claude_mpm/agents/templates/pm_red_flags.md +240 -0
  33. claude_mpm/agents/templates/product_owner.json +338 -0
  34. claude_mpm/agents/templates/project_organizer.json +14 -4
  35. claude_mpm/agents/templates/prompt-engineer.json +13 -2
  36. claude_mpm/agents/templates/python_engineer.json +174 -81
  37. claude_mpm/agents/templates/qa.json +11 -2
  38. claude_mpm/agents/templates/react_engineer.json +16 -3
  39. claude_mpm/agents/templates/refactoring_engineer.json +12 -2
  40. claude_mpm/agents/templates/research.json +34 -21
  41. claude_mpm/agents/templates/response_format.md +583 -0
  42. claude_mpm/agents/templates/ruby-engineer.json +129 -192
  43. claude_mpm/agents/templates/rust_engineer.json +270 -0
  44. claude_mpm/agents/templates/security.json +10 -2
  45. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  46. claude_mpm/agents/templates/ticketing.json +10 -2
  47. claude_mpm/agents/templates/typescript_engineer.json +116 -125
  48. claude_mpm/agents/templates/validation_templates.md +312 -0
  49. claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
  50. claude_mpm/agents/templates/version_control.json +12 -2
  51. claude_mpm/agents/templates/web_qa.json +11 -2
  52. claude_mpm/agents/templates/web_ui.json +15 -2
  53. claude_mpm/cli/__init__.py +34 -614
  54. claude_mpm/cli/commands/agent_manager.py +25 -12
  55. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  56. claude_mpm/cli/commands/agents.py +235 -148
  57. claude_mpm/cli/commands/agents_detect.py +380 -0
  58. claude_mpm/cli/commands/agents_recommend.py +309 -0
  59. claude_mpm/cli/commands/aggregate.py +7 -3
  60. claude_mpm/cli/commands/analyze.py +9 -4
  61. claude_mpm/cli/commands/analyze_code.py +7 -2
  62. claude_mpm/cli/commands/auto_configure.py +570 -0
  63. claude_mpm/cli/commands/config.py +47 -13
  64. claude_mpm/cli/commands/configure.py +419 -1571
  65. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  66. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  67. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  68. claude_mpm/cli/commands/configure_models.py +18 -0
  69. claude_mpm/cli/commands/configure_navigation.py +167 -0
  70. claude_mpm/cli/commands/configure_paths.py +104 -0
  71. claude_mpm/cli/commands/configure_persistence.py +254 -0
  72. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  73. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  74. claude_mpm/cli/commands/configure_validators.py +73 -0
  75. claude_mpm/cli/commands/local_deploy.py +537 -0
  76. claude_mpm/cli/commands/memory.py +54 -20
  77. claude_mpm/cli/commands/mpm_init.py +585 -196
  78. claude_mpm/cli/commands/mpm_init_handler.py +37 -3
  79. claude_mpm/cli/commands/search.py +170 -4
  80. claude_mpm/cli/commands/upgrade.py +152 -0
  81. claude_mpm/cli/executor.py +202 -0
  82. claude_mpm/cli/helpers.py +105 -0
  83. claude_mpm/cli/interactive/__init__.py +3 -0
  84. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  85. claude_mpm/cli/parsers/__init__.py +7 -1
  86. claude_mpm/cli/parsers/agents_parser.py +9 -0
  87. claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
  88. claude_mpm/cli/parsers/base_parser.py +110 -3
  89. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  90. claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
  91. claude_mpm/cli/shared/output_formatters.py +28 -19
  92. claude_mpm/cli/startup.py +481 -0
  93. claude_mpm/cli/utils.py +52 -1
  94. claude_mpm/commands/mpm-agents-detect.md +168 -0
  95. claude_mpm/commands/mpm-agents-recommend.md +214 -0
  96. claude_mpm/commands/mpm-agents.md +75 -1
  97. claude_mpm/commands/mpm-auto-configure.md +217 -0
  98. claude_mpm/commands/mpm-help.md +163 -0
  99. claude_mpm/commands/mpm-init.md +148 -3
  100. claude_mpm/commands/mpm-version.md +113 -0
  101. claude_mpm/commands/mpm.md +1 -0
  102. claude_mpm/config/agent_config.py +2 -2
  103. claude_mpm/config/model_config.py +428 -0
  104. claude_mpm/constants.py +1 -0
  105. claude_mpm/core/base_service.py +13 -12
  106. claude_mpm/core/enums.py +452 -0
  107. claude_mpm/core/factories.py +1 -1
  108. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  109. claude_mpm/core/interactive_session.py +9 -3
  110. claude_mpm/core/log_manager.py +2 -0
  111. claude_mpm/core/logging_config.py +6 -2
  112. claude_mpm/core/oneshot_session.py +8 -4
  113. claude_mpm/core/optimized_agent_loader.py +3 -3
  114. claude_mpm/core/output_style_manager.py +12 -192
  115. claude_mpm/core/service_registry.py +5 -1
  116. claude_mpm/core/types.py +2 -9
  117. claude_mpm/core/typing_utils.py +7 -6
  118. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  119. claude_mpm/dashboard/templates/index.html +3 -41
  120. claude_mpm/hooks/__init__.py +20 -0
  121. claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
  122. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  123. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
  124. claude_mpm/hooks/failure_learning/__init__.py +60 -0
  125. claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
  126. claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
  127. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
  128. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  129. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  130. claude_mpm/hooks/kuzu_memory_hook.py +37 -12
  131. claude_mpm/hooks/kuzu_response_hook.py +183 -0
  132. claude_mpm/models/resume_log.py +340 -0
  133. claude_mpm/services/agents/__init__.py +18 -5
  134. claude_mpm/services/agents/auto_config_manager.py +796 -0
  135. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  136. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  137. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  138. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  139. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  140. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  141. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  142. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  143. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  144. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  145. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  146. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  147. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  148. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  149. claude_mpm/services/agents/local_template_manager.py +1 -1
  150. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  151. claude_mpm/services/agents/observers.py +547 -0
  152. claude_mpm/services/agents/recommender.py +568 -0
  153. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  154. claude_mpm/services/command_handler_service.py +11 -5
  155. claude_mpm/services/core/__init__.py +33 -1
  156. claude_mpm/services/core/interfaces/__init__.py +90 -3
  157. claude_mpm/services/core/interfaces/agent.py +184 -0
  158. claude_mpm/services/core/interfaces/health.py +172 -0
  159. claude_mpm/services/core/interfaces/model.py +281 -0
  160. claude_mpm/services/core/interfaces/process.py +372 -0
  161. claude_mpm/services/core/interfaces/project.py +121 -0
  162. claude_mpm/services/core/interfaces/restart.py +307 -0
  163. claude_mpm/services/core/interfaces/stability.py +260 -0
  164. claude_mpm/services/core/memory_manager.py +11 -24
  165. claude_mpm/services/core/models/__init__.py +79 -0
  166. claude_mpm/services/core/models/agent_config.py +381 -0
  167. claude_mpm/services/core/models/health.py +162 -0
  168. claude_mpm/services/core/models/process.py +235 -0
  169. claude_mpm/services/core/models/restart.py +302 -0
  170. claude_mpm/services/core/models/stability.py +264 -0
  171. claude_mpm/services/core/models/toolchain.py +306 -0
  172. claude_mpm/services/core/path_resolver.py +23 -7
  173. claude_mpm/services/diagnostics/__init__.py +2 -2
  174. claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
  175. claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
  176. claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
  177. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
  178. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  179. claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
  180. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  181. claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
  182. claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
  183. claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
  184. claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
  185. claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
  186. claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
  187. claude_mpm/services/diagnostics/models.py +19 -24
  188. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  189. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  190. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  191. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  192. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  193. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  194. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  195. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  196. claude_mpm/services/local_ops/__init__.py +163 -0
  197. claude_mpm/services/local_ops/crash_detector.py +257 -0
  198. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  199. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  200. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  201. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  202. claude_mpm/services/local_ops/health_manager.py +430 -0
  203. claude_mpm/services/local_ops/log_monitor.py +396 -0
  204. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  205. claude_mpm/services/local_ops/process_manager.py +595 -0
  206. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  207. claude_mpm/services/local_ops/restart_manager.py +401 -0
  208. claude_mpm/services/local_ops/restart_policy.py +387 -0
  209. claude_mpm/services/local_ops/state_manager.py +372 -0
  210. claude_mpm/services/local_ops/unified_manager.py +600 -0
  211. claude_mpm/services/mcp_config_manager.py +9 -4
  212. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  213. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  214. claude_mpm/services/mcp_gateway/main.py +30 -0
  215. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
  216. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
  217. claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
  218. claude_mpm/services/mcp_service_verifier.py +1 -1
  219. claude_mpm/services/memory/failure_tracker.py +563 -0
  220. claude_mpm/services/memory_hook_service.py +165 -4
  221. claude_mpm/services/model/__init__.py +147 -0
  222. claude_mpm/services/model/base_provider.py +365 -0
  223. claude_mpm/services/model/claude_provider.py +412 -0
  224. claude_mpm/services/model/model_router.py +453 -0
  225. claude_mpm/services/model/ollama_provider.py +415 -0
  226. claude_mpm/services/monitor/daemon_manager.py +3 -2
  227. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  228. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  229. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  230. claude_mpm/services/monitor/server.py +2 -1
  231. claude_mpm/services/project/__init__.py +23 -0
  232. claude_mpm/services/project/detection_strategies.py +719 -0
  233. claude_mpm/services/project/toolchain_analyzer.py +581 -0
  234. claude_mpm/services/self_upgrade_service.py +342 -0
  235. claude_mpm/services/session_management_service.py +3 -2
  236. claude_mpm/services/session_manager.py +205 -1
  237. claude_mpm/services/shared/async_service_base.py +16 -27
  238. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  239. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  240. claude_mpm/services/socketio/handlers/hook.py +13 -2
  241. claude_mpm/services/socketio/handlers/registry.py +4 -2
  242. claude_mpm/services/socketio/server/main.py +10 -8
  243. claude_mpm/services/subprocess_launcher_service.py +14 -5
  244. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
  245. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
  246. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
  247. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
  248. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
  249. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  250. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  251. claude_mpm/services/unified/deployment_strategies/local.py +6 -5
  252. claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
  253. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
  254. claude_mpm/services/unified/interfaces.py +3 -1
  255. claude_mpm/services/unified/unified_analyzer.py +14 -10
  256. claude_mpm/services/unified/unified_config.py +2 -1
  257. claude_mpm/services/unified/unified_deployment.py +9 -4
  258. claude_mpm/services/version_service.py +104 -1
  259. claude_mpm/skills/__init__.py +21 -0
  260. claude_mpm/skills/bundled/__init__.py +6 -0
  261. claude_mpm/skills/bundled/api-documentation.md +393 -0
  262. claude_mpm/skills/bundled/async-testing.md +571 -0
  263. claude_mpm/skills/bundled/code-review.md +143 -0
  264. claude_mpm/skills/bundled/database-migration.md +199 -0
  265. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  266. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  267. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  268. claude_mpm/skills/bundled/git-workflow.md +414 -0
  269. claude_mpm/skills/bundled/imagemagick.md +204 -0
  270. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  271. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  272. claude_mpm/skills/bundled/pdf.md +141 -0
  273. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  274. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  275. claude_mpm/skills/bundled/security-scanning.md +327 -0
  276. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  277. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  278. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  279. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  280. claude_mpm/skills/bundled/xlsx.md +157 -0
  281. claude_mpm/skills/registry.py +286 -0
  282. claude_mpm/skills/skill_manager.py +310 -0
  283. claude_mpm/storage/state_storage.py +15 -15
  284. claude_mpm/tools/code_tree_analyzer.py +177 -141
  285. claude_mpm/tools/code_tree_events.py +4 -2
  286. claude_mpm/utils/agent_dependency_loader.py +40 -20
  287. claude_mpm/utils/display_helper.py +260 -0
  288. claude_mpm/utils/git_analyzer.py +407 -0
  289. claude_mpm/utils/robust_installer.py +73 -19
  290. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
  291. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
  292. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  293. claude_mpm/dashboard/static/index-hub-backup.html +0 -713
  294. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  295. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  296. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  297. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  298. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  299. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  300. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  301. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  302. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  303. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  304. claude_mpm/services/project/analyzer_refactored.py +0 -450
  305. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
  306. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
  307. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
  308. {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
@@ -14,6 +14,7 @@ import sys
14
14
  from pathlib import Path
15
15
  from typing import Any, Dict, List, Optional
16
16
 
17
+ from ...core.enums import OutputFormat
17
18
  from ...core.logging_config import get_logger
18
19
  from ...services.agents.agent_builder import AgentBuilderService
19
20
  from ...services.agents.deployment.agent_deployment import AgentDeploymentService
@@ -36,6 +37,18 @@ class AgentManagerCommand(AgentCommand):
36
37
  self.deployment_service = AgentDeploymentService()
37
38
  return self.deployment_service
38
39
 
40
+ def _get_output_format(self, args) -> str:
41
+ """
42
+ Get output format from args with enum default.
43
+
44
+ Args:
45
+ args: Command arguments
46
+
47
+ Returns:
48
+ Output format string (compatible with both enum and string usage)
49
+ """
50
+ return getattr(args, "format", OutputFormat.TEXT)
51
+
39
52
  def run(self, args) -> CommandResult:
40
53
  """Execute agent manager command.
41
54
 
@@ -122,8 +135,8 @@ class AgentManagerCommand(AgentCommand):
122
135
  )
123
136
 
124
137
  # Format output
125
- output_format = getattr(args, "format", "text")
126
- if output_format == "json":
138
+ output_format = self._get_output_format(args)
139
+ if str(output_format).lower() == OutputFormat.JSON:
127
140
  return CommandResult.success_result("Agents listed", data=agents)
128
141
  output = self._format_agent_list(agents)
129
142
  return CommandResult.success_result(output)
@@ -288,8 +301,8 @@ class AgentManagerCommand(AgentCommand):
288
301
  if not agent_info:
289
302
  return CommandResult.error_result(f"Agent '{agent_id}' not found")
290
303
 
291
- output_format = getattr(args, "format", "text")
292
- if output_format == "json":
304
+ output_format = self._get_output_format(args)
305
+ if str(output_format).lower() == OutputFormat.JSON:
293
306
  return CommandResult.success_result("Agent details", data=agent_info)
294
307
  output = self._format_agent_details(agent_info)
295
308
  return CommandResult.success_result(output)
@@ -332,8 +345,8 @@ class AgentManagerCommand(AgentCommand):
332
345
  """List available agent templates."""
333
346
  templates = self.builder_service.list_available_templates()
334
347
 
335
- output_format = getattr(args, "format", "text")
336
- if output_format == "json":
348
+ output_format = self._get_output_format(args)
349
+ if str(output_format).lower() == OutputFormat.JSON:
337
350
  return CommandResult.success_result("Templates listed", data=templates)
338
351
  output = "Available Agent Templates:\n\n"
339
352
  for template in templates:
@@ -357,7 +370,7 @@ class AgentManagerCommand(AgentCommand):
357
370
  clean_user = not getattr(args, "project_only", False)
358
371
  dry_run = getattr(args, "dry_run", False)
359
372
  force = getattr(args, "force", False)
360
- output_format = getattr(args, "format", "text")
373
+ output_format = self._get_output_format(args)
361
374
 
362
375
  # Track results
363
376
  results = {
@@ -397,7 +410,7 @@ class AgentManagerCommand(AgentCommand):
397
410
  )
398
411
 
399
412
  # Handle output based on format
400
- if output_format == "json":
413
+ if str(output_format).lower() == OutputFormat.JSON:
401
414
  return CommandResult.success_result("Reset completed", data=results)
402
415
 
403
416
  # Generate text output
@@ -858,9 +871,9 @@ class AgentManagerCommand(AgentCommand):
858
871
  return CommandResult.success_result("No local agent templates found")
859
872
 
860
873
  # Format output
861
- output_format = getattr(args, "format", "text")
874
+ output_format = self._get_output_format(args)
862
875
 
863
- if output_format == "json":
876
+ if str(output_format).lower() == OutputFormat.JSON:
864
877
  data = [
865
878
  {
866
879
  "id": t.agent_id,
@@ -1379,8 +1392,8 @@ def manage_agent_manager(args) -> int:
1379
1392
 
1380
1393
  if result.success:
1381
1394
  # Handle JSON output format
1382
- output_format = getattr(args, "format", "text")
1383
- if output_format == "json" and result.data is not None:
1395
+ output_format = getattr(args, "format", OutputFormat.TEXT)
1396
+ if str(output_format).lower() == OutputFormat.JSON and result.data is not None:
1384
1397
  print(json.dumps(result.data, indent=2))
1385
1398
  elif result.message:
1386
1399
  print(result.message)
@@ -0,0 +1,186 @@
1
+ """Agent state management for configure command.
2
+
3
+ This module provides state persistence for agent enable/disable operations,
4
+ maintaining consistency between in-memory state and filesystem state.
5
+
6
+ Coverage: 100% - Safe to extract and refactor independently.
7
+ """
8
+
9
+ import json
10
+ import logging
11
+ from pathlib import Path
12
+ from typing import Dict, List
13
+
14
+ from claude_mpm.cli.commands.configure_models import AgentConfig
15
+
16
+
17
+ class SimpleAgentManager:
18
+ """Simple agent state management that discovers real agents from templates.
19
+
20
+ This class handles:
21
+ - Loading agent states from filesystem
22
+ - Tracking pending enable/disable operations
23
+ - Committing state changes to disk
24
+ - Rolling back failed operations
25
+
26
+ 100% test coverage ensures this can be safely refactored.
27
+ """
28
+
29
+ def __init__(self, config_dir: Path):
30
+ """Initialize agent manager.
31
+
32
+ Args:
33
+ config_dir: Path to .claude-mpm directory
34
+ """
35
+ self.config_dir = config_dir
36
+ self.config_file = config_dir / "agent_states.json"
37
+ self.config_dir.mkdir(parents=True, exist_ok=True)
38
+ self._load_states()
39
+ # Path to agent templates directory
40
+ self.templates_dir = (
41
+ Path(__file__).parent.parent.parent / "agents" / "templates"
42
+ )
43
+ # Add logger for error reporting
44
+ self.logger = logging.getLogger(__name__)
45
+ # Track pending changes for batch operations
46
+ self.deferred_changes: Dict[str, bool] = {}
47
+
48
+ def _load_states(self):
49
+ """Load agent states from file."""
50
+ if self.config_file.exists():
51
+ with self.config_file.open() as f:
52
+ self.states = json.load(f)
53
+ else:
54
+ self.states = {}
55
+
56
+ def _save_states(self):
57
+ """Save agent states to file."""
58
+ with self.config_file.open("w") as f:
59
+ json.dump(self.states, f, indent=2)
60
+
61
+ def is_agent_enabled(self, agent_name: str) -> bool:
62
+ """Check if an agent is enabled."""
63
+ return self.states.get(agent_name, {}).get("enabled", True)
64
+
65
+ def set_agent_enabled(self, agent_name: str, enabled: bool):
66
+ """Set agent enabled state."""
67
+ if agent_name not in self.states:
68
+ self.states[agent_name] = {}
69
+ self.states[agent_name]["enabled"] = enabled
70
+ self._save_states()
71
+
72
+ def set_agent_enabled_deferred(self, agent_name: str, enabled: bool) -> None:
73
+ """Queue agent state change without saving."""
74
+ self.deferred_changes[agent_name] = enabled
75
+
76
+ def commit_deferred_changes(self) -> None:
77
+ """Save all deferred changes at once."""
78
+ for agent_name, enabled in self.deferred_changes.items():
79
+ if agent_name not in self.states:
80
+ self.states[agent_name] = {}
81
+ self.states[agent_name]["enabled"] = enabled
82
+ self._save_states()
83
+ self.deferred_changes.clear()
84
+
85
+ def discard_deferred_changes(self) -> None:
86
+ """Discard all pending changes."""
87
+ self.deferred_changes.clear()
88
+
89
+ def get_pending_state(self, agent_name: str) -> bool:
90
+ """Get agent state including pending changes."""
91
+ if agent_name in self.deferred_changes:
92
+ return self.deferred_changes[agent_name]
93
+ return self.states.get(agent_name, {}).get("enabled", True)
94
+
95
+ def has_pending_changes(self) -> bool:
96
+ """Check if there are unsaved changes."""
97
+ return len(self.deferred_changes) > 0
98
+
99
+ def discover_agents(self) -> List[AgentConfig]:
100
+ """Discover available agents from template JSON files."""
101
+ agents = []
102
+
103
+ # Scan templates directory for JSON files
104
+ if not self.templates_dir.exists():
105
+ # Fallback to a minimal set if templates dir doesn't exist
106
+ return [
107
+ AgentConfig("engineer", "Engineering agent (templates not found)", []),
108
+ AgentConfig("research", "Research agent (templates not found)", []),
109
+ ]
110
+
111
+ try:
112
+ # Read all JSON template files
113
+ for template_file in sorted(self.templates_dir.glob("*.json")):
114
+ # Skip backup files
115
+ if "backup" in template_file.name.lower():
116
+ continue
117
+
118
+ try:
119
+ with template_file.open() as f:
120
+ template_data = json.load(f)
121
+
122
+ # Extract agent information from template
123
+ agent_id = template_data.get("agent_id", template_file.stem)
124
+
125
+ # Get metadata for display info
126
+ metadata = template_data.get("metadata", {})
127
+ metadata.get("name", agent_id)
128
+ description = metadata.get(
129
+ "description", "No description available"
130
+ )
131
+
132
+ # Extract capabilities/tools as dependencies for display
133
+ capabilities = template_data.get("capabilities", {})
134
+ tools = capabilities.get("tools", [])
135
+ # Ensure tools is a list before slicing
136
+ if not isinstance(tools, list):
137
+ tools = []
138
+ # Show first few tools as "dependencies" for UI purposes
139
+ display_tools = tools[:3] if len(tools) > 3 else tools
140
+
141
+ # Normalize agent ID (remove -agent suffix if present, replace underscores)
142
+ normalized_id = agent_id.replace("-agent", "").replace("_", "-")
143
+
144
+ agents.append(
145
+ AgentConfig(
146
+ name=normalized_id,
147
+ description=(
148
+ description[:80] + "..."
149
+ if len(description) > 80
150
+ else description
151
+ ),
152
+ dependencies=display_tools,
153
+ )
154
+ )
155
+
156
+ except (json.JSONDecodeError, KeyError) as e:
157
+ # Log malformed templates but continue
158
+ self.logger.debug(
159
+ f"Skipping malformed template {template_file.name}: {e}"
160
+ )
161
+ continue
162
+ except Exception as e:
163
+ # Log unexpected errors but continue processing other templates
164
+ self.logger.debug(
165
+ f"Error processing template {template_file.name}: {e}"
166
+ )
167
+ continue
168
+
169
+ except Exception as e:
170
+ # If there's a catastrophic error reading templates directory
171
+ self.logger.error(f"Failed to read templates directory: {e}")
172
+ return [
173
+ AgentConfig("engineer", f"Error accessing templates: {e!s}", []),
174
+ AgentConfig("research", "Research agent", []),
175
+ ]
176
+
177
+ # Sort agents by name for consistent display
178
+ agents.sort(key=lambda a: a.name)
179
+
180
+ return (
181
+ agents
182
+ if agents
183
+ else [
184
+ AgentConfig("engineer", "No agents found in templates", []),
185
+ ]
186
+ )