claude-mpm 4.13.2__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 (250) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_ENGINEER.md +286 -0
  3. claude_mpm/agents/BASE_PM.md +48 -17
  4. claude_mpm/agents/OUTPUT_STYLE.md +329 -11
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
  6. claude_mpm/agents/agent_loader.py +17 -5
  7. claude_mpm/agents/frontmatter_validator.py +284 -253
  8. claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
  9. claude_mpm/agents/templates/api_qa.json +7 -1
  10. claude_mpm/agents/templates/clerk-ops.json +8 -1
  11. claude_mpm/agents/templates/code_analyzer.json +4 -1
  12. claude_mpm/agents/templates/dart_engineer.json +11 -1
  13. claude_mpm/agents/templates/data_engineer.json +11 -1
  14. claude_mpm/agents/templates/documentation.json +6 -1
  15. claude_mpm/agents/templates/engineer.json +18 -1
  16. claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
  17. claude_mpm/agents/templates/golang_engineer.json +11 -1
  18. claude_mpm/agents/templates/java_engineer.json +12 -2
  19. claude_mpm/agents/templates/local_ops_agent.json +1217 -6
  20. claude_mpm/agents/templates/nextjs_engineer.json +11 -1
  21. claude_mpm/agents/templates/ops.json +8 -1
  22. claude_mpm/agents/templates/php-engineer.json +11 -1
  23. claude_mpm/agents/templates/project_organizer.json +10 -3
  24. claude_mpm/agents/templates/prompt-engineer.json +5 -1
  25. claude_mpm/agents/templates/python_engineer.json +11 -1
  26. claude_mpm/agents/templates/qa.json +7 -1
  27. claude_mpm/agents/templates/react_engineer.json +11 -1
  28. claude_mpm/agents/templates/refactoring_engineer.json +8 -1
  29. claude_mpm/agents/templates/research.json +4 -1
  30. claude_mpm/agents/templates/ruby-engineer.json +11 -1
  31. claude_mpm/agents/templates/rust_engineer.json +11 -1
  32. claude_mpm/agents/templates/security.json +6 -1
  33. claude_mpm/agents/templates/svelte-engineer.json +225 -0
  34. claude_mpm/agents/templates/ticketing.json +6 -1
  35. claude_mpm/agents/templates/typescript_engineer.json +11 -1
  36. claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
  37. claude_mpm/agents/templates/version_control.json +8 -1
  38. claude_mpm/agents/templates/web_qa.json +7 -1
  39. claude_mpm/agents/templates/web_ui.json +11 -1
  40. claude_mpm/cli/__init__.py +34 -706
  41. claude_mpm/cli/commands/agent_manager.py +25 -12
  42. claude_mpm/cli/commands/agent_state_manager.py +186 -0
  43. claude_mpm/cli/commands/agents.py +204 -148
  44. claude_mpm/cli/commands/aggregate.py +7 -3
  45. claude_mpm/cli/commands/analyze.py +9 -4
  46. claude_mpm/cli/commands/analyze_code.py +7 -2
  47. claude_mpm/cli/commands/auto_configure.py +7 -9
  48. claude_mpm/cli/commands/config.py +47 -13
  49. claude_mpm/cli/commands/configure.py +294 -1788
  50. claude_mpm/cli/commands/configure_agent_display.py +261 -0
  51. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  52. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  53. claude_mpm/cli/commands/configure_models.py +18 -0
  54. claude_mpm/cli/commands/configure_navigation.py +167 -0
  55. claude_mpm/cli/commands/configure_paths.py +104 -0
  56. claude_mpm/cli/commands/configure_persistence.py +254 -0
  57. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  58. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  59. claude_mpm/cli/commands/configure_validators.py +73 -0
  60. claude_mpm/cli/commands/local_deploy.py +537 -0
  61. claude_mpm/cli/commands/memory.py +54 -20
  62. claude_mpm/cli/commands/mpm_init.py +39 -25
  63. claude_mpm/cli/commands/mpm_init_handler.py +8 -3
  64. claude_mpm/cli/executor.py +202 -0
  65. claude_mpm/cli/helpers.py +105 -0
  66. claude_mpm/cli/interactive/__init__.py +3 -0
  67. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  68. claude_mpm/cli/parsers/__init__.py +7 -1
  69. claude_mpm/cli/parsers/base_parser.py +98 -3
  70. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  71. claude_mpm/cli/shared/output_formatters.py +28 -19
  72. claude_mpm/cli/startup.py +481 -0
  73. claude_mpm/cli/utils.py +52 -1
  74. claude_mpm/commands/mpm-help.md +3 -0
  75. claude_mpm/commands/mpm-version.md +113 -0
  76. claude_mpm/commands/mpm.md +1 -0
  77. claude_mpm/config/agent_config.py +2 -2
  78. claude_mpm/config/model_config.py +428 -0
  79. claude_mpm/core/base_service.py +13 -12
  80. claude_mpm/core/enums.py +452 -0
  81. claude_mpm/core/factories.py +1 -1
  82. claude_mpm/core/instruction_reinforcement_hook.py +2 -1
  83. claude_mpm/core/interactive_session.py +9 -3
  84. claude_mpm/core/logging_config.py +6 -2
  85. claude_mpm/core/oneshot_session.py +8 -4
  86. claude_mpm/core/optimized_agent_loader.py +3 -3
  87. claude_mpm/core/output_style_manager.py +12 -192
  88. claude_mpm/core/service_registry.py +5 -1
  89. claude_mpm/core/types.py +2 -9
  90. claude_mpm/core/typing_utils.py +7 -6
  91. claude_mpm/dashboard/static/js/dashboard.js +0 -14
  92. claude_mpm/dashboard/templates/index.html +3 -41
  93. claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
  94. claude_mpm/hooks/instruction_reinforcement.py +7 -2
  95. claude_mpm/models/resume_log.py +340 -0
  96. claude_mpm/services/agents/auto_config_manager.py +10 -11
  97. claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
  98. claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
  99. claude_mpm/services/agents/deployment/agent_validator.py +17 -1
  100. claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
  101. claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
  102. claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
  103. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
  104. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
  105. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
  106. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
  107. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
  108. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
  109. claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
  110. claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
  111. claude_mpm/services/agents/local_template_manager.py +1 -1
  112. claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
  113. claude_mpm/services/agents/registry/modification_tracker.py +5 -2
  114. claude_mpm/services/command_handler_service.py +11 -5
  115. claude_mpm/services/core/interfaces/__init__.py +74 -2
  116. claude_mpm/services/core/interfaces/health.py +172 -0
  117. claude_mpm/services/core/interfaces/model.py +281 -0
  118. claude_mpm/services/core/interfaces/process.py +372 -0
  119. claude_mpm/services/core/interfaces/restart.py +307 -0
  120. claude_mpm/services/core/interfaces/stability.py +260 -0
  121. claude_mpm/services/core/models/__init__.py +33 -0
  122. claude_mpm/services/core/models/agent_config.py +12 -28
  123. claude_mpm/services/core/models/health.py +162 -0
  124. claude_mpm/services/core/models/process.py +235 -0
  125. claude_mpm/services/core/models/restart.py +302 -0
  126. claude_mpm/services/core/models/stability.py +264 -0
  127. claude_mpm/services/core/path_resolver.py +23 -7
  128. claude_mpm/services/diagnostics/__init__.py +2 -2
  129. claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
  130. claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
  131. claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
  132. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
  133. claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
  134. claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
  135. claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
  136. claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
  137. claude_mpm/services/diagnostics/checks/mcp_services_check.py +36 -31
  138. claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
  139. claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
  140. claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
  141. claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
  142. claude_mpm/services/diagnostics/models.py +19 -24
  143. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
  144. claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
  145. claude_mpm/services/infrastructure/monitoring/base.py +5 -13
  146. claude_mpm/services/infrastructure/monitoring/network.py +7 -6
  147. claude_mpm/services/infrastructure/monitoring/process.py +13 -12
  148. claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
  149. claude_mpm/services/infrastructure/monitoring/service.py +16 -15
  150. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  151. claude_mpm/services/local_ops/__init__.py +163 -0
  152. claude_mpm/services/local_ops/crash_detector.py +257 -0
  153. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  154. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  155. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  156. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  157. claude_mpm/services/local_ops/health_manager.py +430 -0
  158. claude_mpm/services/local_ops/log_monitor.py +396 -0
  159. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  160. claude_mpm/services/local_ops/process_manager.py +595 -0
  161. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  162. claude_mpm/services/local_ops/restart_manager.py +401 -0
  163. claude_mpm/services/local_ops/restart_policy.py +387 -0
  164. claude_mpm/services/local_ops/state_manager.py +372 -0
  165. claude_mpm/services/local_ops/unified_manager.py +600 -0
  166. claude_mpm/services/mcp_config_manager.py +9 -4
  167. claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
  168. claude_mpm/services/mcp_gateway/core/base.py +18 -31
  169. claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +71 -24
  170. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
  171. claude_mpm/services/memory_hook_service.py +4 -1
  172. claude_mpm/services/model/__init__.py +147 -0
  173. claude_mpm/services/model/base_provider.py +365 -0
  174. claude_mpm/services/model/claude_provider.py +412 -0
  175. claude_mpm/services/model/model_router.py +453 -0
  176. claude_mpm/services/model/ollama_provider.py +415 -0
  177. claude_mpm/services/monitor/daemon_manager.py +3 -2
  178. claude_mpm/services/monitor/handlers/dashboard.py +2 -1
  179. claude_mpm/services/monitor/handlers/hooks.py +2 -1
  180. claude_mpm/services/monitor/management/lifecycle.py +3 -2
  181. claude_mpm/services/monitor/server.py +2 -1
  182. claude_mpm/services/session_management_service.py +3 -2
  183. claude_mpm/services/session_manager.py +205 -1
  184. claude_mpm/services/shared/async_service_base.py +16 -27
  185. claude_mpm/services/shared/lifecycle_service_base.py +1 -14
  186. claude_mpm/services/socketio/handlers/__init__.py +5 -2
  187. claude_mpm/services/socketio/handlers/hook.py +13 -2
  188. claude_mpm/services/socketio/handlers/registry.py +4 -2
  189. claude_mpm/services/socketio/server/main.py +10 -8
  190. claude_mpm/services/subprocess_launcher_service.py +14 -5
  191. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
  192. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
  193. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
  194. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
  195. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
  196. claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
  197. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
  198. claude_mpm/services/unified/deployment_strategies/local.py +6 -5
  199. claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
  200. claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
  201. claude_mpm/services/unified/interfaces.py +3 -1
  202. claude_mpm/services/unified/unified_analyzer.py +14 -10
  203. claude_mpm/services/unified/unified_config.py +2 -1
  204. claude_mpm/services/unified/unified_deployment.py +9 -4
  205. claude_mpm/services/version_service.py +104 -1
  206. claude_mpm/skills/__init__.py +21 -0
  207. claude_mpm/skills/bundled/__init__.py +6 -0
  208. claude_mpm/skills/bundled/api-documentation.md +393 -0
  209. claude_mpm/skills/bundled/async-testing.md +571 -0
  210. claude_mpm/skills/bundled/code-review.md +143 -0
  211. claude_mpm/skills/bundled/database-migration.md +199 -0
  212. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  213. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  214. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  215. claude_mpm/skills/bundled/git-workflow.md +414 -0
  216. claude_mpm/skills/bundled/imagemagick.md +204 -0
  217. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  218. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  219. claude_mpm/skills/bundled/pdf.md +141 -0
  220. claude_mpm/skills/bundled/performance-profiling.md +567 -0
  221. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  222. claude_mpm/skills/bundled/security-scanning.md +327 -0
  223. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  224. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  225. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  226. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  227. claude_mpm/skills/bundled/xlsx.md +157 -0
  228. claude_mpm/skills/registry.py +286 -0
  229. claude_mpm/skills/skill_manager.py +310 -0
  230. claude_mpm/tools/code_tree_analyzer.py +177 -141
  231. claude_mpm/tools/code_tree_events.py +4 -2
  232. claude_mpm/utils/agent_dependency_loader.py +2 -2
  233. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
  234. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
  235. claude_mpm/dashboard/static/css/code-tree.css +0 -1639
  236. claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
  237. claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
  238. claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
  239. claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
  240. claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
  241. claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
  242. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
  243. claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
  244. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
  245. claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
  246. claude_mpm/services/project/analyzer_refactored.py +0 -450
  247. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
  248. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
  249. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
  250. {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,261 @@
1
+ """Agent display and table rendering for configure command.
2
+
3
+ WHY: Separate agent display logic from main configure command to improve
4
+ modularity and reduce complexity. Agent display includes table rendering,
5
+ status indicators, and detailed agent information views.
6
+
7
+ DESIGN DECISIONS:
8
+ - Use Rich library for modern table formatting
9
+ - Support pending state visualization (enable/disable arrows)
10
+ - Show truncated descriptions in tables, full details in views
11
+ - Display template metadata when available
12
+ """
13
+
14
+ import json
15
+ from typing import List
16
+
17
+ from rich.box import ROUNDED
18
+ from rich.console import Console
19
+ from rich.panel import Panel
20
+ from rich.prompt import Prompt
21
+ from rich.table import Table
22
+ from rich.text import Text
23
+
24
+ from .configure_models import AgentConfig
25
+
26
+
27
+ class AgentDisplay:
28
+ """Handle agent display and table rendering.
29
+
30
+ This class manages the visual presentation of agents in various formats:
31
+ - Summary tables with status indicators
32
+ - Pending state visualization with arrows
33
+ - Detailed agent information panels
34
+ """
35
+
36
+ def __init__(
37
+ self,
38
+ console: Console,
39
+ agent_manager, # SimpleAgentManager instance
40
+ get_template_path_fn, # Function to get template path for an agent
41
+ display_header_fn, # Function to display configure header
42
+ ):
43
+ """Initialize agent display handler.
44
+
45
+ Args:
46
+ console: Rich console for output
47
+ agent_manager: SimpleAgentManager instance for state queries
48
+ get_template_path_fn: Function(agent_name) -> Path to get template path
49
+ display_header_fn: Function() -> None to display configure header
50
+ """
51
+ self.console = console
52
+ self.agent_manager = agent_manager
53
+ self._get_agent_template_path = get_template_path_fn
54
+ self._display_header = display_header_fn
55
+
56
+ def display_agents_table(self, agents: List[AgentConfig]) -> None:
57
+ """Display a table of available agents with status and metadata.
58
+
59
+ Shows:
60
+ - Agent ID (for selection)
61
+ - Name and description
62
+ - Enable/disable status
63
+ - Model or tools information
64
+
65
+ Args:
66
+ agents: List of agent configurations to display
67
+ """
68
+ table = Table(
69
+ title=f"Available Agents ({len(agents)} total)",
70
+ box=ROUNDED,
71
+ show_lines=True,
72
+ )
73
+
74
+ table.add_column("ID", style="dim", width=3)
75
+ table.add_column("Name", style="bold blue", width=22)
76
+ table.add_column("Status", width=12)
77
+ table.add_column("Description", style="bold", width=45)
78
+ table.add_column("Model/Tools", style="dim", width=20)
79
+
80
+ for idx, agent in enumerate(agents, 1):
81
+ # Check if agent is enabled
82
+ is_enabled = self.agent_manager.is_agent_enabled(agent.name)
83
+ status = (
84
+ "[green]✓ Enabled[/green]" if is_enabled else "[red]✗ Disabled[/red]"
85
+ )
86
+
87
+ # Format tools/dependencies - show first 2 tools
88
+ tools_display = ""
89
+ if agent.dependencies:
90
+ if len(agent.dependencies) > 2:
91
+ tools_display = f"{', '.join(agent.dependencies[:2])}..."
92
+ else:
93
+ tools_display = ", ".join(agent.dependencies)
94
+ else:
95
+ # Try to get model from template
96
+ try:
97
+ template_path = self._get_agent_template_path(agent.name)
98
+ if template_path.exists():
99
+ with template_path.open() as f:
100
+ template = json.load(f)
101
+ model = template.get("capabilities", {}).get("model", "default")
102
+ tools_display = f"Model: {model}"
103
+ else:
104
+ tools_display = "Default"
105
+ except Exception:
106
+ tools_display = "Default"
107
+
108
+ # Truncate description for table display with bright styling
109
+ if len(agent.description) > 42:
110
+ desc_display = f"[cyan]{agent.description[:42]}[/cyan][dim]...[/dim]"
111
+ else:
112
+ desc_display = f"[cyan]{agent.description}[/cyan]"
113
+
114
+ table.add_row(str(idx), agent.name, status, desc_display, tools_display)
115
+
116
+ self.console.print(table)
117
+
118
+ def display_agents_with_pending_states(self, agents: List[AgentConfig]) -> None:
119
+ """Display agents table with pending state indicators.
120
+
121
+ Shows arrows (→) for agents with pending state changes:
122
+ - "✗ Disabled → ✓ Enabled" for pending enable
123
+ - "✓ Enabled → ✗ Disabled" for pending disable
124
+
125
+ Useful for batch operations where changes are deferred until save.
126
+
127
+ Args:
128
+ agents: List of agent configurations to display
129
+ """
130
+ has_pending = self.agent_manager.has_pending_changes()
131
+ pending_count = len(self.agent_manager.deferred_changes) if has_pending else 0
132
+
133
+ title = f"Available Agents ({len(agents)} total)"
134
+ if has_pending:
135
+ title += f" [yellow]({pending_count} change{'s' if pending_count != 1 else ''} pending)[/yellow]"
136
+
137
+ table = Table(title=title, box=ROUNDED, show_lines=True, expand=True)
138
+ table.add_column("ID", justify="right", style="bold blue", width=5)
139
+ table.add_column("Name", style="bold", width=22)
140
+ table.add_column("Status", width=20)
141
+ table.add_column("Description", style="bold", width=45)
142
+
143
+ for idx, agent in enumerate(agents, 1):
144
+ current_state = self.agent_manager.is_agent_enabled(agent.name)
145
+ pending_state = self.agent_manager.get_pending_state(agent.name)
146
+
147
+ # Show pending status with arrow
148
+ if current_state != pending_state:
149
+ if pending_state:
150
+ status = "[yellow]✗ Disabled → ✓ Enabled[/yellow]"
151
+ else:
152
+ status = "[yellow]✓ Enabled → ✗ Disabled[/yellow]"
153
+ else:
154
+ status = (
155
+ "[green]✓ Enabled[/green]"
156
+ if current_state
157
+ else "[dim]✗ Disabled[/dim]"
158
+ )
159
+
160
+ desc_display = Text()
161
+ desc_display.append(
162
+ (
163
+ agent.description[:42] + "..."
164
+ if len(agent.description) > 42
165
+ else agent.description
166
+ ),
167
+ style="",
168
+ )
169
+
170
+ table.add_row(str(idx), agent.name, status, desc_display)
171
+
172
+ self.console.print(table)
173
+
174
+ def view_agent_details(self, agents: List[AgentConfig]) -> None:
175
+ """View detailed information about a selected agent.
176
+
177
+ Displays comprehensive agent information in a panel:
178
+ - Name, status, template path
179
+ - Full description (not truncated)
180
+ - Model and version information
181
+ - Tags and tools
182
+ - Whether it's a system or custom template
183
+
184
+ Args:
185
+ agents: List of available agents for selection
186
+ """
187
+ agent_id = Prompt.ask("Enter agent ID to view")
188
+
189
+ try:
190
+ idx = int(agent_id) - 1
191
+ if 0 <= idx < len(agents):
192
+ agent = agents[idx]
193
+
194
+ self.console.clear()
195
+ self._display_header()
196
+
197
+ # Try to load full template for more details
198
+ template_path = self._get_agent_template_path(agent.name)
199
+ extra_info = ""
200
+
201
+ if template_path.exists():
202
+ try:
203
+ with template_path.open() as f:
204
+ template = json.load(f)
205
+
206
+ # Extract additional information
207
+ metadata = template.get("metadata", {})
208
+ capabilities = template.get("capabilities", {})
209
+
210
+ # Get full description if available
211
+ full_desc = metadata.get("description", agent.description)
212
+
213
+ # Get model and tools
214
+ model = capabilities.get("model", "default")
215
+ tools = capabilities.get("tools", [])
216
+
217
+ # Get tags
218
+ tags = metadata.get("tags", [])
219
+
220
+ # Get version info
221
+ agent_version = template.get("agent_version", "N/A")
222
+ schema_version = template.get("schema_version", "N/A")
223
+
224
+ extra_info = f"""
225
+ [bold]Full Description:[/bold]
226
+ {full_desc}
227
+
228
+ [bold]Model:[/bold] {model}
229
+ [bold]Agent Version:[/bold] {agent_version}
230
+ [bold]Schema Version:[/bold] {schema_version}
231
+ [bold]Tags:[/bold] {', '.join(tags) if tags else 'None'}
232
+ [bold]Tools:[/bold] {', '.join(tools[:5]) if tools else 'None'}{'...' if len(tools) > 5 else ''}
233
+ """
234
+ except Exception:
235
+ pass
236
+
237
+ # Create detail panel
238
+ detail_text = f"""
239
+ [bold]Name:[/bold] {agent.name}
240
+ [bold]Status:[/bold] {'[green]Enabled[/green]' if self.agent_manager.is_agent_enabled(agent.name) else '[red]Disabled[/red]'}
241
+ [bold]Template Path:[/bold] {template_path}
242
+ [bold]Is System Template:[/bold] {'Yes' if str(template_path).startswith(str(self.agent_manager.templates_dir)) else 'No (Custom)'}
243
+ {extra_info}
244
+ """
245
+
246
+ panel = Panel(
247
+ detail_text.strip(),
248
+ title=f"[bold]{agent.name} Details[/bold]",
249
+ box=ROUNDED,
250
+ style="blue",
251
+ )
252
+
253
+ self.console.print(panel)
254
+
255
+ else:
256
+ self.console.print("[red]Invalid agent ID.[/red]")
257
+
258
+ except ValueError:
259
+ self.console.print("[red]Invalid input. Please enter a number.[/red]")
260
+
261
+ Prompt.ask("\nPress Enter to continue")
@@ -0,0 +1,204 @@
1
+ """Behavior file management for configure command.
2
+
3
+ This module handles operations on behavior configuration files including
4
+ identity and workflow configurations.
5
+
6
+ Extracted from configure.py (Phase 5/9) to reduce God Object complexity.
7
+ """
8
+
9
+ import shutil
10
+ from pathlib import Path
11
+ from typing import Optional
12
+
13
+ from rich.box import ROUNDED
14
+ from rich.console import Console
15
+ from rich.prompt import Prompt
16
+ from rich.table import Table
17
+ from rich.text import Text
18
+
19
+ from ...utils.console import console as default_console
20
+ from ..shared import CommandResult
21
+
22
+
23
+ class BehaviorManager:
24
+ """Manage behavior configuration files.
25
+
26
+ Handles:
27
+ - Displaying available behavior files
28
+ - Editing identity and workflow configs
29
+ - Importing/exporting behavior files
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ config_dir: Path,
35
+ current_scope: str = "project",
36
+ console: Optional[Console] = None,
37
+ ):
38
+ """Initialize behavior manager.
39
+
40
+ Args:
41
+ config_dir: Path to configuration directory
42
+ current_scope: Current scope (project or user)
43
+ console: Rich console for output (optional)
44
+ """
45
+ self.config_dir = config_dir
46
+ self.current_scope = current_scope
47
+ self.behaviors_dir = config_dir / "behaviors"
48
+ self.console = console or default_console
49
+
50
+ # Ensure behaviors directory exists
51
+ self.behaviors_dir.mkdir(parents=True, exist_ok=True)
52
+
53
+ def manage_behaviors(self) -> None:
54
+ """Interactive behavior file management interface.
55
+
56
+ Extracted from ConfigureCommand._manage_behaviors()
57
+ """
58
+ while True:
59
+ self.console.clear()
60
+ # Note: _display_header() is called from parent
61
+ # We skip it here since it's a parent responsibility
62
+
63
+ self.console.print("[bold]Behavior File Management[/bold]\n")
64
+
65
+ # Display current behavior files
66
+ self.display_behavior_files()
67
+
68
+ # Show behavior menu
69
+ self.console.print("\n[bold]Options:[/bold]")
70
+
71
+ text_1 = Text(" ")
72
+ text_1.append("[1]", style="bold blue")
73
+ text_1.append(" Edit identity configuration")
74
+ self.console.print(text_1)
75
+
76
+ text_2 = Text(" ")
77
+ text_2.append("[2]", style="bold blue")
78
+ text_2.append(" Edit workflow configuration")
79
+ self.console.print(text_2)
80
+
81
+ text_3 = Text(" ")
82
+ text_3.append("[3]", style="bold blue")
83
+ text_3.append(" Import behavior file")
84
+ self.console.print(text_3)
85
+
86
+ text_4 = Text(" ")
87
+ text_4.append("[4]", style="bold blue")
88
+ text_4.append(" Export behavior file")
89
+ self.console.print(text_4)
90
+
91
+ text_b = Text(" ")
92
+ text_b.append("[b]", style="bold blue")
93
+ text_b.append(" Back to main menu")
94
+ self.console.print(text_b)
95
+
96
+ self.console.print()
97
+
98
+ choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="b")
99
+
100
+ if choice == "b":
101
+ break
102
+ if choice == "1":
103
+ self.edit_identity_config()
104
+ elif choice == "2":
105
+ self.edit_workflow_config()
106
+ elif choice == "3":
107
+ self.import_behavior_file()
108
+ elif choice == "4":
109
+ self.export_behavior_file()
110
+ else:
111
+ self.console.print("[red]Invalid choice.[/red]")
112
+ Prompt.ask("Press Enter to continue")
113
+
114
+ def display_behavior_files(self) -> None:
115
+ """Display current behavior files.
116
+
117
+ Extracted from ConfigureCommand._display_behavior_files()
118
+ """
119
+ table = Table(title="Behavior Files", box=ROUNDED)
120
+ table.add_column("File", style="bold blue", width=30)
121
+ table.add_column("Size", style="dim", width=10)
122
+ table.add_column("Modified", style="", width=20)
123
+
124
+ identity_file = self.behaviors_dir / "identity.yaml"
125
+ workflow_file = self.behaviors_dir / "workflow.yaml"
126
+
127
+ for file_path in [identity_file, workflow_file]:
128
+ if file_path.exists():
129
+ stat = file_path.stat()
130
+ size = f"{stat.st_size} bytes"
131
+ modified = f"{stat.st_mtime:.0f}" # Simplified timestamp
132
+ table.add_row(file_path.name, size, modified)
133
+ else:
134
+ table.add_row(file_path.name, "[dim]Not found[/dim]", "-")
135
+
136
+ self.console.print(table)
137
+
138
+ def edit_identity_config(self) -> None:
139
+ """Edit identity configuration.
140
+
141
+ Extracted from ConfigureCommand._edit_identity_config()
142
+ """
143
+ self.console.print(
144
+ "[yellow]Identity configuration editor - Coming soon![/yellow]"
145
+ )
146
+ Prompt.ask("Press Enter to continue")
147
+
148
+ def edit_workflow_config(self) -> None:
149
+ """Edit workflow configuration.
150
+
151
+ Extracted from ConfigureCommand._edit_workflow_config()
152
+ """
153
+ self.console.print(
154
+ "[yellow]Workflow configuration editor - Coming soon![/yellow]"
155
+ )
156
+ Prompt.ask("Press Enter to continue")
157
+
158
+ def import_behavior_file(self) -> None:
159
+ """Import a behavior file.
160
+
161
+ Extracted from ConfigureCommand._import_behavior_file()
162
+ """
163
+ file_path = Prompt.ask("Enter path to behavior file to import")
164
+
165
+ try:
166
+ source = Path(file_path)
167
+ if not source.exists():
168
+ self.console.print(f"[red]File not found: {file_path}[/red]")
169
+ return
170
+
171
+ # Copy file
172
+ target = self.behaviors_dir / source.name
173
+ shutil.copy2(source, target)
174
+
175
+ self.console.print(f"[green]Successfully imported {source.name}![/green]")
176
+
177
+ except Exception as e:
178
+ self.console.print(f"[red]Error importing file: {e}[/red]")
179
+
180
+ Prompt.ask("Press Enter to continue")
181
+
182
+ def export_behavior_file(self) -> None:
183
+ """Export a behavior file.
184
+
185
+ Extracted from ConfigureCommand._export_behavior_file()
186
+ """
187
+ self.console.print("[yellow]Behavior file export - Coming soon![/yellow]")
188
+ Prompt.ask("Press Enter to continue")
189
+
190
+ def run_behavior_management(self) -> CommandResult:
191
+ """Run behavior management interface.
192
+
193
+ Extracted from ConfigureCommand._run_behavior_management()
194
+
195
+ Returns:
196
+ CommandResult with status
197
+ """
198
+ try:
199
+ self.manage_behaviors()
200
+ return CommandResult.success_result("Behavior management completed")
201
+ except KeyboardInterrupt:
202
+ return CommandResult.success_result("Behavior management cancelled")
203
+ except Exception as e:
204
+ return CommandResult.error_result(f"Behavior management failed: {e}")
@@ -0,0 +1,225 @@
1
+ """Git hook installation and management for configure command.
2
+
3
+ This module handles installation, verification, and removal of git hooks
4
+ used by Claude MPM for automated workflows.
5
+
6
+ Extracted from configure.py (Phase 7/9) to reduce God Object complexity.
7
+ """
8
+
9
+ from rich.console import Console
10
+ from rich.prompt import Confirm
11
+
12
+ from ...utils.console import console as default_console
13
+ from ..shared import CommandResult
14
+
15
+
16
+ class HookManager:
17
+ """Manage git hook installation and verification.
18
+
19
+ Handles:
20
+ - Installing Claude Code integration hooks
21
+ - Verifying hook installation status
22
+ - Uninstalling hooks when requested
23
+ """
24
+
25
+ def __init__(self, console: Console = None):
26
+ """Initialize hook manager.
27
+
28
+ Args:
29
+ console: Rich console for output (optional, defaults to shared console)
30
+ """
31
+ self.console = console or default_console
32
+ self.logger = None # Will be set from parent if needed
33
+
34
+ def install_hooks(self, force: bool = False) -> CommandResult:
35
+ """Install Claude MPM hooks for Claude Code integration.
36
+
37
+ Extracted from ConfigureCommand._install_hooks() (CC=11)
38
+
39
+ Args:
40
+ force: Force reinstallation even if hooks exist
41
+
42
+ Returns:
43
+ CommandResult with installation status
44
+ """
45
+ try:
46
+ from ...hooks.claude_hooks.installer import HookInstaller
47
+
48
+ installer = HookInstaller()
49
+
50
+ # Check Claude Code version compatibility first
51
+ is_compatible, version_message = installer.is_version_compatible()
52
+ self.console.print("[cyan]Checking Claude Code version...[/cyan]")
53
+ self.console.print(version_message)
54
+
55
+ if not is_compatible:
56
+ self.console.print(
57
+ "\n[yellow]⚠ Hook monitoring is not available for your Claude Code version.[/yellow]"
58
+ )
59
+ self.console.print(
60
+ "The dashboard and other features will work without real-time monitoring."
61
+ )
62
+ self.console.print(
63
+ f"\n[dim]To enable monitoring, upgrade Claude Code to version {installer.MIN_CLAUDE_VERSION} or higher.[/dim]"
64
+ )
65
+ return CommandResult.success_result(
66
+ "Version incompatible with hook monitoring",
67
+ data={"compatible": False, "message": version_message},
68
+ )
69
+
70
+ # Check current status
71
+ status = installer.get_status()
72
+ if status["installed"] and not force:
73
+ self.console.print("[yellow]Hooks are already installed.[/yellow]")
74
+ self.console.print("Use --force to reinstall.")
75
+
76
+ if not status["valid"]:
77
+ self.console.print("\n[red]However, there are issues:[/red]")
78
+ for issue in status["issues"]:
79
+ self.console.print(f" - {issue}")
80
+
81
+ return CommandResult.success_result(
82
+ "Hooks already installed", data=status
83
+ )
84
+
85
+ # Install hooks
86
+ self.console.print("[cyan]Installing Claude MPM hooks...[/cyan]")
87
+ success = installer.install_hooks(force=force)
88
+
89
+ if success:
90
+ self.console.print("[green]✓ Hooks installed successfully![/green]")
91
+ self.console.print("\nYou can now use /mpm commands in Claude Code:")
92
+ self.console.print(" /mpm - Show help")
93
+ self.console.print(" /mpm status - Show claude-mpm status")
94
+
95
+ # Verify installation
96
+ is_valid, issues = installer.verify_hooks()
97
+ if not is_valid:
98
+ self.console.print(
99
+ "\n[yellow]Warning: Installation completed but verification found issues:[/yellow]"
100
+ )
101
+ for issue in issues:
102
+ self.console.print(f" - {issue}")
103
+
104
+ return CommandResult.success_result("Hooks installed successfully")
105
+ self.console.print("[red]✗ Hook installation failed[/red]")
106
+ return CommandResult.error_result("Hook installation failed")
107
+
108
+ except ImportError:
109
+ self.console.print("[red]Error: HookInstaller module not found[/red]")
110
+ self.console.print("Please ensure claude-mpm is properly installed.")
111
+ return CommandResult.error_result("HookInstaller module not found")
112
+ except Exception as e:
113
+ if self.logger:
114
+ self.logger.error(f"Hook installation error: {e}", exc_info=True)
115
+ return CommandResult.error_result(f"Hook installation failed: {e}")
116
+
117
+ def verify_hooks(self) -> CommandResult:
118
+ """Verify that Claude MPM hooks are properly installed.
119
+
120
+ Extracted from ConfigureCommand._verify_hooks() (CC=10)
121
+
122
+ Returns:
123
+ CommandResult with verification status
124
+ """
125
+ try:
126
+ from ...hooks.claude_hooks.installer import HookInstaller
127
+
128
+ installer = HookInstaller()
129
+ status = installer.get_status()
130
+
131
+ self.console.print("[bold]Hook Installation Status[/bold]\n")
132
+
133
+ # Show Claude Code version and compatibility
134
+ if status.get("claude_version"):
135
+ self.console.print(f"Claude Code Version: {status['claude_version']}")
136
+ if status.get("version_compatible"):
137
+ self.console.print(
138
+ "[green]✓[/green] Version compatible with hook monitoring"
139
+ )
140
+ else:
141
+ self.console.print(
142
+ f"[yellow]⚠[/yellow] {status.get('version_message', 'Version incompatible')}"
143
+ )
144
+ self.console.print()
145
+ else:
146
+ self.console.print(
147
+ "[yellow]Claude Code version could not be detected[/yellow]"
148
+ )
149
+ self.console.print()
150
+
151
+ if status["installed"]:
152
+ self.console.print(
153
+ f"[green]✓[/green] Hooks installed at: {status['hook_script']}"
154
+ )
155
+ else:
156
+ self.console.print("[red]✗[/red] Hooks not installed")
157
+
158
+ if status["settings_file"]:
159
+ self.console.print(
160
+ f"[green]✓[/green] Settings file: {status['settings_file']}"
161
+ )
162
+ else:
163
+ self.console.print("[red]✗[/red] Settings file not found")
164
+
165
+ if status.get("configured_events"):
166
+ self.console.print(
167
+ f"[green]✓[/green] Configured events: {', '.join(status['configured_events'])}"
168
+ )
169
+ else:
170
+ self.console.print("[red]✗[/red] No events configured")
171
+
172
+ if status["valid"]:
173
+ self.console.print("\n[green]All checks passed![/green]")
174
+ else:
175
+ self.console.print("\n[red]Issues found:[/red]")
176
+ for issue in status["issues"]:
177
+ self.console.print(f" - {issue}")
178
+
179
+ return CommandResult.success_result(
180
+ "Hook verification complete", data=status
181
+ )
182
+
183
+ except ImportError:
184
+ self.console.print("[red]Error: HookInstaller module not found[/red]")
185
+ return CommandResult.error_result("HookInstaller module not found")
186
+ except Exception as e:
187
+ if self.logger:
188
+ self.logger.error(f"Hook verification error: {e}", exc_info=True)
189
+ return CommandResult.error_result(f"Hook verification failed: {e}")
190
+
191
+ def uninstall_hooks(self) -> CommandResult:
192
+ """Uninstall Claude MPM hooks.
193
+
194
+ Extracted from ConfigureCommand._uninstall_hooks() (CC=5)
195
+
196
+ Returns:
197
+ CommandResult with uninstallation status
198
+ """
199
+ try:
200
+ from ...hooks.claude_hooks.installer import HookInstaller
201
+
202
+ installer = HookInstaller()
203
+
204
+ # Confirm uninstallation
205
+ if not Confirm.ask(
206
+ "[yellow]Are you sure you want to uninstall Claude MPM hooks?[/yellow]"
207
+ ):
208
+ return CommandResult.success_result("Uninstallation cancelled")
209
+
210
+ self.console.print("[cyan]Uninstalling Claude MPM hooks...[/cyan]")
211
+ success = installer.uninstall_hooks()
212
+
213
+ if success:
214
+ self.console.print("[green]✓ Hooks uninstalled successfully![/green]")
215
+ return CommandResult.success_result("Hooks uninstalled successfully")
216
+ self.console.print("[red]✗ Hook uninstallation failed[/red]")
217
+ return CommandResult.error_result("Hook uninstallation failed")
218
+
219
+ except ImportError:
220
+ self.console.print("[red]Error: HookInstaller module not found[/red]")
221
+ return CommandResult.error_result("HookInstaller module not found")
222
+ except Exception as e:
223
+ if self.logger:
224
+ self.logger.error(f"Hook uninstallation error: {e}", exc_info=True)
225
+ return CommandResult.error_result(f"Hook uninstallation failed: {e}")