claude-mpm 4.0.23__py3-none-any.whl → 4.0.25__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 (60) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +4 -1
  4. claude_mpm/agents/BASE_PM.md +3 -0
  5. claude_mpm/agents/templates/code_analyzer.json +2 -2
  6. claude_mpm/cli/commands/agents.py +453 -113
  7. claude_mpm/cli/commands/aggregate.py +107 -15
  8. claude_mpm/cli/commands/cleanup.py +142 -10
  9. claude_mpm/cli/commands/config.py +358 -224
  10. claude_mpm/cli/commands/info.py +184 -75
  11. claude_mpm/cli/commands/mcp_command_router.py +5 -76
  12. claude_mpm/cli/commands/mcp_install_commands.py +68 -36
  13. claude_mpm/cli/commands/mcp_server_commands.py +30 -37
  14. claude_mpm/cli/commands/memory.py +331 -61
  15. claude_mpm/cli/commands/monitor.py +101 -7
  16. claude_mpm/cli/commands/run.py +368 -8
  17. claude_mpm/cli/commands/tickets.py +206 -24
  18. claude_mpm/cli/parsers/mcp_parser.py +3 -0
  19. claude_mpm/cli/shared/__init__.py +40 -0
  20. claude_mpm/cli/shared/argument_patterns.py +212 -0
  21. claude_mpm/cli/shared/command_base.py +234 -0
  22. claude_mpm/cli/shared/error_handling.py +238 -0
  23. claude_mpm/cli/shared/output_formatters.py +231 -0
  24. claude_mpm/config/agent_config.py +29 -8
  25. claude_mpm/core/container.py +6 -4
  26. claude_mpm/core/service_registry.py +4 -2
  27. claude_mpm/core/shared/__init__.py +17 -0
  28. claude_mpm/core/shared/config_loader.py +320 -0
  29. claude_mpm/core/shared/path_resolver.py +277 -0
  30. claude_mpm/core/shared/singleton_manager.py +208 -0
  31. claude_mpm/hooks/claude_hooks/memory_integration.py +4 -2
  32. claude_mpm/hooks/claude_hooks/response_tracking.py +14 -3
  33. claude_mpm/hooks/memory_integration_hook.py +11 -2
  34. claude_mpm/services/agents/deployment/agent_deployment.py +43 -23
  35. claude_mpm/services/agents/deployment/deployment_wrapper.py +71 -0
  36. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +1 -0
  37. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +43 -0
  38. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +4 -0
  39. claude_mpm/services/agents/deployment/processors/agent_processor.py +1 -1
  40. claude_mpm/services/agents/loading/base_agent_manager.py +11 -3
  41. claude_mpm/services/agents/registry/deployed_agent_discovery.py +14 -5
  42. claude_mpm/services/event_aggregator.py +4 -2
  43. claude_mpm/services/mcp_gateway/config/config_loader.py +89 -28
  44. claude_mpm/services/mcp_gateway/config/configuration.py +29 -0
  45. claude_mpm/services/mcp_gateway/registry/service_registry.py +22 -5
  46. claude_mpm/services/memory/builder.py +6 -1
  47. claude_mpm/services/response_tracker.py +3 -1
  48. claude_mpm/services/runner_configuration_service.py +15 -6
  49. claude_mpm/services/shared/__init__.py +20 -0
  50. claude_mpm/services/shared/async_service_base.py +219 -0
  51. claude_mpm/services/shared/config_service_base.py +292 -0
  52. claude_mpm/services/shared/lifecycle_service_base.py +317 -0
  53. claude_mpm/services/shared/manager_base.py +303 -0
  54. claude_mpm/services/shared/service_factory.py +308 -0
  55. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/METADATA +19 -13
  56. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/RECORD +60 -44
  57. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/WHEEL +0 -0
  58. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/entry_points.txt +0 -0
  59. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/licenses/LICENSE +0 -0
  60. {claude_mpm-4.0.23.dist-info → claude_mpm-4.0.25.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- from pathlib import Path
2
-
3
1
  """
4
2
  Configuration management commands for claude-mpm CLI.
5
3
 
@@ -8,13 +6,15 @@ the command line. This module provides commands for configuration validation,
8
6
  viewing, and troubleshooting.
9
7
 
10
8
  DESIGN DECISIONS:
11
- - Integrate with existing CLI structure
12
- - Provide clear, actionable output
13
- - Support both validation and viewing operations
14
- - Use consistent error codes for CI/CD integration
9
+ - Use BaseCommand for consistent CLI patterns
10
+ - Leverage shared utilities for argument parsing and output formatting
11
+ - Provide clear, actionable output with standardized error handling
12
+ - Support multiple output formats (json, yaml, table, text)
15
13
  """
16
14
 
17
15
  import json
16
+ from pathlib import Path
17
+ from typing import Dict, Any
18
18
 
19
19
  import yaml
20
20
  from rich.panel import Panel
@@ -22,273 +22,407 @@ from rich.syntax import Syntax
22
22
  from rich.table import Table
23
23
 
24
24
  from ...core.config import Config
25
- from ...core.logger import get_logger
26
25
  from ...utils.console import console
26
+ from ..shared import BaseCommand, CommandResult, add_config_arguments, add_output_arguments
27
27
 
28
- logger = get_logger(__name__)
29
-
30
-
31
- def manage_config(args) -> int:
32
- """Main entry point for configuration management commands.
33
-
34
- WHY: This dispatcher handles different configuration subcommands,
35
- routing to the appropriate handler based on user input.
36
-
37
- Args:
38
- args: Parsed command line arguments
39
28
 
40
- Returns:
41
- Exit code (0 for success, non-zero for failure)
42
- """
43
- if args.config_command == "validate":
44
- return validate_config(args)
45
- elif args.config_command == "view":
46
- return view_config(args)
47
- elif args.config_command == "status":
48
- return show_config_status(args)
49
- else:
50
- console.print(f"[red]Unknown config command: {args.config_command}[/red]")
51
- return 1
29
+ class ConfigCommand(BaseCommand):
30
+ """Configuration management command using shared utilities."""
52
31
 
32
+ def __init__(self):
33
+ super().__init__("config")
53
34
 
54
- def validate_config(args) -> int:
55
- """Validate configuration file.
35
+ def validate_args(self, args) -> str:
36
+ """Validate command arguments."""
37
+ if not hasattr(args, 'config_command') or not args.config_command:
38
+ return "No config command specified"
56
39
 
57
- WHY: Users need immediate feedback on configuration validity with
58
- clear guidance on how to fix any issues found.
59
-
60
- Args:
61
- args: Command line arguments including config file path
62
-
63
- Returns:
64
- Exit code (0=valid, 1=errors, 2=warnings in strict mode)
65
- """
66
- config_file = args.config_file or Path(".claude-mpm/configuration.yaml")
40
+ valid_commands = ["validate", "view", "status"]
41
+ if args.config_command not in valid_commands:
42
+ return f"Unknown config command: {args.config_command}. Valid commands: {', '.join(valid_commands)}"
67
43
 
68
- console.print(f"\n[bold blue]Validating configuration: {config_file}[/bold blue]\n")
44
+ return None
69
45
 
70
- # Check if file exists
71
- if not config_file.exists():
72
- console.print(f"[red]✗ Configuration file not found: {config_file}[/red]")
73
- console.print(
74
- f"[yellow]→ Create with: mkdir -p {config_file.parent} && touch {config_file}[/yellow]"
75
- )
76
- return 1
77
-
78
- try:
79
- # Try to load configuration
80
- config = Config(config_file=config_file)
81
-
82
- # Validate configuration
83
- is_valid, errors, warnings = config.validate_configuration()
84
-
85
- # Display results
86
- if errors:
87
- console.print("[bold red]ERRORS:[/bold red]")
88
- for error in errors:
89
- console.print(f" [red]✗ {error}[/red]")
90
-
91
- if warnings:
92
- console.print("\n[bold yellow]WARNINGS:[/bold yellow]")
93
- for warning in warnings:
94
- console.print(f" [yellow]⚠ {warning}[/yellow]")
95
-
96
- # Show summary
97
- if is_valid and not warnings:
98
- console.print("\n[green]✓ Configuration is valid[/green]")
99
- return 0
100
- elif is_valid and warnings:
101
- console.print(
102
- f"\n[green]✓ Configuration is valid with {len(warnings)} warning(s)[/green]"
103
- )
104
- return 2 if args.strict else 0
46
+ def run(self, args) -> CommandResult:
47
+ """Execute the configuration command."""
48
+ if args.config_command == "validate":
49
+ return self._validate_config(args)
50
+ elif args.config_command == "view":
51
+ return self._view_config(args)
52
+ elif args.config_command == "status":
53
+ return self._show_config_status(args)
105
54
  else:
106
- console.print(
107
- f"\n[red]✗ Configuration validation failed with {len(errors)} error(s)[/red]"
108
- )
109
- console.print(
110
- "\n[yellow]Run 'python scripts/validate_configuration.py' for detailed analysis[/yellow]"
111
- )
112
- return 1
55
+ return CommandResult.error_result(f"Unknown config command: {args.config_command}")
113
56
 
114
- except Exception as e:
115
- console.print(f"[red]Failed to validate configuration: {e}[/red]")
116
- logger.exception("Configuration validation error")
117
- return 1
57
+ def _validate_config(self, args) -> CommandResult:
58
+ """Validate configuration file."""
59
+ config_file = getattr(args, 'config_file', None) or Path(".claude-mpm/configuration.yaml")
118
60
 
61
+ # Check if file exists
62
+ if not config_file.exists():
63
+ error_msg = f"Configuration file not found: {config_file}"
64
+ suggestion = f"Create with: mkdir -p {config_file.parent} && touch {config_file}"
119
65
 
120
- def view_config(args) -> int:
121
- """View current configuration.
66
+ if getattr(args, 'format', 'text') in ['json', 'yaml']:
67
+ return CommandResult.error_result(
68
+ error_msg,
69
+ data={"suggestion": suggestion, "config_file": str(config_file)}
70
+ )
71
+ else:
72
+ console.print(f"[red]✗ {error_msg}[/red]")
73
+ console.print(f"[yellow]→ {suggestion}[/yellow]")
74
+ return CommandResult.error_result(error_msg)
75
+
76
+ try:
77
+ # Load and validate configuration
78
+ if config_file != Path(".claude-mpm/configuration.yaml"):
79
+ # Use specific config file
80
+ config = Config(config_file=config_file)
81
+ else:
82
+ # Use default config
83
+ config = self.config
84
+ is_valid, errors, warnings = config.validate_configuration()
85
+
86
+ # Prepare result data
87
+ result_data = {
88
+ "config_file": str(config_file),
89
+ "valid": is_valid,
90
+ "errors": errors,
91
+ "warnings": warnings,
92
+ "error_count": len(errors),
93
+ "warning_count": len(warnings)
94
+ }
95
+
96
+ # Handle output format
97
+ output_format = getattr(args, 'format', 'text')
98
+ if output_format in ['json', 'yaml']:
99
+ if is_valid and not warnings:
100
+ return CommandResult.success_result("Configuration is valid", data=result_data)
101
+ elif is_valid and warnings:
102
+ message = f"Configuration is valid with {len(warnings)} warning(s)"
103
+ exit_code = 2 if getattr(args, 'strict', False) else 0
104
+ return CommandResult(success=True, exit_code=exit_code, message=message, data=result_data)
105
+ else:
106
+ return CommandResult.error_result(
107
+ f"Configuration validation failed with {len(errors)} error(s)",
108
+ data=result_data
109
+ )
110
+ else:
111
+ # Rich console output for text format
112
+ console.print(f"\n[bold blue]Validating configuration: {config_file}[/bold blue]\n")
113
+
114
+ if errors:
115
+ console.print("[bold red]ERRORS:[/bold red]")
116
+ for error in errors:
117
+ console.print(f" [red]✗ {error}[/red]")
118
+
119
+ if warnings:
120
+ console.print("\n[bold yellow]WARNINGS:[/bold yellow]")
121
+ for warning in warnings:
122
+ console.print(f" [yellow]⚠ {warning}[/yellow]")
123
+
124
+ # Show summary
125
+ if is_valid and not warnings:
126
+ console.print("\n[green]✓ Configuration is valid[/green]")
127
+ return CommandResult.success_result("Configuration is valid")
128
+ elif is_valid and warnings:
129
+ console.print(f"\n[green]✓ Configuration is valid with {len(warnings)} warning(s)[/green]")
130
+ exit_code = 2 if getattr(args, 'strict', False) else 0
131
+ return CommandResult(success=True, exit_code=exit_code, message="Configuration valid with warnings")
132
+ else:
133
+ console.print(f"\n[red]✗ Configuration validation failed with {len(errors)} error(s)[/red]")
134
+ console.print("\n[yellow]Run 'python scripts/validate_configuration.py' for detailed analysis[/yellow]")
135
+ return CommandResult.error_result("Configuration validation failed")
136
+
137
+ except Exception as e:
138
+ self.logger.error(f"Configuration validation error: {e}", exc_info=True)
139
+
140
+ if getattr(args, 'format', 'text') in ['json', 'yaml']:
141
+ return CommandResult.error_result(
142
+ f"Failed to validate configuration: {e}",
143
+ data={"config_file": str(config_file), "exception": str(e)}
144
+ )
145
+ else:
146
+ console.print(f"[red]Failed to validate configuration: {e}[/red]")
147
+ return CommandResult.error_result(f"Failed to validate configuration: {e}")
148
+
149
+ def _view_config(self, args) -> CommandResult:
150
+ """View current configuration."""
151
+ try:
152
+ # Load configuration
153
+ config_file = getattr(args, 'config_file', None)
154
+ config = Config(config_file=config_file)
155
+
156
+ # Get configuration as dictionary
157
+ config_dict = config.to_dict()
158
+
159
+ # Filter by section if specified
160
+ section = getattr(args, 'section', None)
161
+ if section:
162
+ if section in config_dict:
163
+ config_dict = {section: config_dict[section]}
164
+ else:
165
+ error_msg = f"Section '{section}' not found in configuration"
166
+ available_sections = list(config_dict.keys())
167
+
168
+ if getattr(args, 'format', 'text') in ['json', 'yaml']:
169
+ return CommandResult.error_result(
170
+ error_msg,
171
+ data={"available_sections": available_sections}
172
+ )
173
+ else:
174
+ console.print(f"[red]{error_msg}[/red]")
175
+ console.print(f"[yellow]Available sections: {', '.join(available_sections)}[/yellow]")
176
+ return CommandResult.error_result(error_msg)
177
+
178
+ # Handle output format
179
+ output_format = getattr(args, 'format', 'text')
180
+
181
+ if output_format == "json":
182
+ if hasattr(args, 'output') and args.output:
183
+ # Use shared output handling
184
+ return CommandResult.success_result("Configuration retrieved", data=config_dict)
185
+ else:
186
+ # Direct console output with syntax highlighting
187
+ output = json.dumps(config_dict, indent=2)
188
+ syntax = Syntax(output, "json", theme="monokai", line_numbers=False)
189
+ console.print(syntax)
190
+ return CommandResult.success_result("Configuration displayed", data=config_dict)
191
+
192
+ elif output_format == "yaml":
193
+ if hasattr(args, 'output') and args.output:
194
+ # Use shared output handling
195
+ return CommandResult.success_result("Configuration retrieved", data=config_dict)
196
+ else:
197
+ # Direct console output with syntax highlighting
198
+ output = yaml.dump(config_dict, default_flow_style=False, sort_keys=False)
199
+ syntax = Syntax(output, "yaml", theme="monokai", line_numbers=False)
200
+ console.print(syntax)
201
+ return CommandResult.success_result("Configuration displayed")
202
+
203
+ elif output_format == "table":
204
+ self._display_config_table(config_dict)
205
+ return CommandResult.success_result("Configuration displayed")
206
+
207
+ else: # text format
208
+ self._display_config_table(config_dict)
209
+ return CommandResult.success_result("Configuration displayed")
210
+
211
+ except Exception as e:
212
+ self.logger.error(f"Configuration view error: {e}", exc_info=True)
213
+
214
+ if getattr(args, 'format', 'text') in ['json', 'yaml']:
215
+ return CommandResult.error_result(
216
+ f"Failed to view configuration: {e}",
217
+ data={"exception": str(e)}
218
+ )
219
+ else:
220
+ console.print(f"[red]Failed to view configuration: {e}[/red]")
221
+ return CommandResult.error_result(f"Failed to view configuration: {e}")
122
222
 
123
- WHY: Users need to see their effective configuration including
124
- defaults and environment variable overrides.
223
+ def _show_config_status(self, args) -> CommandResult:
224
+ """Show configuration status and health."""
225
+ try:
226
+ # Load configuration
227
+ config_file = getattr(args, 'config_file', None)
228
+ config = Config(config_file=config_file)
125
229
 
126
- Args:
127
- args: Command line arguments
230
+ # Get status
231
+ status = config.get_configuration_status()
128
232
 
129
- Returns:
130
- Exit code (0 for success)
131
- """
132
- try:
133
- # Load configuration
134
- config_file = args.config_file
135
- config = Config(config_file=config_file)
136
-
137
- # Get configuration as dictionary
138
- config_dict = config.to_dict()
139
-
140
- # Filter by section if specified
141
- if args.section:
142
- if args.section in config_dict:
143
- config_dict = {args.section: config_dict[args.section]}
144
- else:
145
- console.print(
146
- f"[red]Section '{args.section}' not found in configuration[/red]"
147
- )
148
- return 1
233
+ # Handle output format
234
+ output_format = getattr(args, 'format', 'text')
149
235
 
150
- # Format output
151
- if args.format == "json":
152
- output = json.dumps(config_dict, indent=2)
153
- syntax = Syntax(output, "json", theme="monokai", line_numbers=False)
154
- console.print(syntax)
155
- elif args.format == "yaml":
156
- output = yaml.dump(config_dict, default_flow_style=False, sort_keys=False)
157
- syntax = Syntax(output, "yaml", theme="monokai", line_numbers=False)
158
- console.print(syntax)
159
- else: # table format
160
- display_config_table(config_dict)
236
+ if output_format in ['json', 'yaml']:
237
+ # Structured output
238
+ result_data = status.copy()
161
239
 
162
- return 0
240
+ # Add response logging details if requested
241
+ if getattr(args, 'check_response_logging', False):
242
+ result_data['response_logging_config'] = config.get("response_logging", {})
163
243
 
164
- except Exception as e:
165
- console.print(f"[red]Failed to view configuration: {e}[/red]")
166
- logger.exception("Configuration view error")
167
- return 1
244
+ if status["valid"]:
245
+ return CommandResult.success_result("Configuration status retrieved", data=result_data)
246
+ else:
247
+ return CommandResult.error_result("Configuration has issues", data=result_data)
168
248
 
249
+ else:
250
+ # Rich console output for text format
251
+ self._display_status_panel(status)
169
252
 
170
- def show_config_status(args) -> int:
171
- """Show configuration status and health.
253
+ # Show detailed errors/warnings if verbose
254
+ if getattr(args, 'verbose', False):
255
+ self._display_detailed_status(status)
172
256
 
173
- WHY: Users need a quick way to check if their configuration is
174
- working correctly, especially for response logging.
257
+ # Check response logging specifically
258
+ if getattr(args, 'check_response_logging', False):
259
+ self._display_response_logging_config(config)
175
260
 
176
- Args:
177
- args: Command line arguments
261
+ return CommandResult.success_result("Configuration status displayed") if status["valid"] else CommandResult.error_result("Configuration has issues")
178
262
 
179
- Returns:
180
- Exit code (0 for success)
181
- """
182
- try:
183
- # Load configuration
184
- config = Config(config_file=args.config_file)
263
+ except Exception as e:
264
+ self.logger.error(f"Configuration status error: {e}", exc_info=True)
185
265
 
186
- # Get status
187
- status = config.get_configuration_status()
266
+ if getattr(args, 'format', 'text') in ['json', 'yaml']:
267
+ return CommandResult.error_result(
268
+ f"Failed to get configuration status: {e}",
269
+ data={"exception": str(e)}
270
+ )
271
+ else:
272
+ console.print(f"[red]Failed to get configuration status: {e}[/red]")
273
+ return CommandResult.error_result(f"Failed to get configuration status: {e}")
188
274
 
189
- # Create status panel
275
+ def _display_status_panel(self, status: Dict[str, Any]) -> None:
276
+ """Display configuration status panel."""
190
277
  panel_content = []
191
278
 
192
279
  # Basic info
193
280
  panel_content.append(f"[bold]Configuration Status[/bold]")
194
- panel_content.append(f"Valid: {'✓' if status['valid'] else '✗'}")
281
+ panel_content.append(f"Valid: {'✓' if status.get('valid', False) else '✗'}")
195
282
  panel_content.append(f"Loaded from: {status.get('loaded_from', 'defaults')}")
196
- panel_content.append(f"Total keys: {status['key_count']}")
197
-
198
- # Feature status
199
- panel_content.append("\n[bold]Features:[/bold]")
200
- panel_content.append(
201
- f"Response Logging: {'✓ Enabled' if status['response_logging_enabled'] else '✗ Disabled'}"
202
- )
203
- panel_content.append(
204
- f"Memory System: {'✓ Enabled' if status['memory_enabled'] else '✗ Disabled'}"
205
- )
283
+ panel_content.append(f"Total keys: {status.get('key_count', 'unknown')}")
284
+
285
+ # Feature status (only if available)
286
+ if 'response_logging_enabled' in status or 'memory_enabled' in status:
287
+ panel_content.append("\n[bold]Features:[/bold]")
288
+ if 'response_logging_enabled' in status:
289
+ panel_content.append(
290
+ f"Response Logging: {'✓ Enabled' if status['response_logging_enabled'] else '✗ Disabled'}"
291
+ )
292
+ if 'memory_enabled' in status:
293
+ panel_content.append(
294
+ f"Memory System: {'✓ Enabled' if status['memory_enabled'] else '✗ Disabled'}"
295
+ )
206
296
 
207
- # Errors and warnings
208
- if status["errors"]:
297
+ # Errors and warnings (only if available)
298
+ if status.get("errors"):
209
299
  panel_content.append(f"\n[red]Errors: {len(status['errors'])}[/red]")
210
- if status["warnings"]:
211
- panel_content.append(
212
- f"\n[yellow]Warnings: {len(status['warnings'])}[/yellow]"
213
- )
300
+ if status.get("warnings"):
301
+ panel_content.append(f"\n[yellow]Warnings: {len(status['warnings'])}[/yellow]")
214
302
 
215
303
  # Display panel
216
304
  panel = Panel(
217
305
  "\n".join(panel_content),
218
306
  title="Configuration Status",
219
- border_style="green" if status["valid"] else "red",
307
+ border_style="green" if status.get("valid", False) else "red",
220
308
  )
221
309
  console.print(panel)
222
310
 
223
- # Show detailed errors/warnings if verbose
224
- if args.verbose:
225
- if status["errors"]:
226
- console.print("\n[bold red]Errors:[/bold red]")
227
- for error in status["errors"]:
228
- console.print(f" [red]• {error}[/red]")
311
+ def _display_detailed_status(self, status: Dict[str, Any]) -> None:
312
+ """Display detailed errors and warnings."""
313
+ if status.get("errors"):
314
+ console.print("\n[bold red]Errors:[/bold red]")
315
+ for error in status["errors"]:
316
+ console.print(f" [red]• {error}[/red]")
317
+
318
+ if status.get("warnings"):
319
+ console.print("\n[bold yellow]Warnings:[/bold yellow]")
320
+ for warning in status["warnings"]:
321
+ console.print(f" [yellow]• {warning}[/yellow]")
322
+
323
+ def _display_response_logging_config(self, config: Config) -> None:
324
+ """Display response logging configuration table."""
325
+ console.print("\n[bold]Response Logging Configuration:[/bold]")
326
+ rl_config = config.get("response_logging", {})
327
+
328
+ table = Table(show_header=True)
329
+ table.add_column("Setting", style="cyan")
330
+ table.add_column("Value", style="white")
331
+
332
+ table.add_row("Enabled", str(rl_config.get("enabled", False)))
333
+ table.add_row("Format", rl_config.get("format", "json"))
334
+ table.add_row("Use Async", str(rl_config.get("use_async", True)))
335
+ table.add_row(
336
+ "Session Directory",
337
+ rl_config.get("session_directory", ".claude-mpm/responses"),
338
+ )
339
+ table.add_row(
340
+ "Compression", str(rl_config.get("enable_compression", False))
341
+ )
342
+
343
+ console.print(table)
344
+
345
+ def _display_config_table(self, config_dict: dict, prefix: str = "") -> None:
346
+ """Display configuration as a formatted table."""
347
+ table = Table(show_header=True, title="Configuration")
348
+ table.add_column("Key", style="cyan", no_wrap=True)
349
+ table.add_column("Value", style="white")
350
+ table.add_column("Type", style="dim")
351
+
352
+ def add_items(d: dict, prefix: str = ""):
353
+ for key, value in d.items():
354
+ full_key = f"{prefix}.{key}" if prefix else key
355
+
356
+ if isinstance(value, dict) and value:
357
+ # Add nested items
358
+ add_items(value, full_key)
359
+ else:
360
+ # Add leaf value
361
+ value_str = str(value)
362
+ if len(value_str) > 50:
363
+ value_str = value_str[:47] + "..."
364
+
365
+ type_str = type(value).__name__
366
+ table.add_row(full_key, value_str, type_str)
367
+
368
+ add_items(config_dict)
369
+ console.print(table)
370
+
371
+ def _flatten_config(self, config: dict, prefix: str = "") -> dict:
372
+ """Flatten nested configuration dictionary."""
373
+ flattened = {}
374
+
375
+ for key, value in config.items():
376
+ new_key = f"{prefix}.{key}" if prefix else key
377
+
378
+ if isinstance(value, dict):
379
+ flattened.update(self._flatten_config(value, new_key))
380
+ elif isinstance(value, list):
381
+ flattened[new_key] = str(value)
382
+ else:
383
+ flattened[new_key] = value
229
384
 
230
- if status["warnings"]:
231
- console.print("\n[bold yellow]Warnings:[/bold yellow]")
232
- for warning in status["warnings"]:
233
- console.print(f" [yellow]• {warning}[/yellow]")
385
+ return flattened
234
386
 
235
- # Check response logging specifically
236
- if args.check_response_logging:
237
- console.print("\n[bold]Response Logging Configuration:[/bold]")
238
- rl_config = config.get("response_logging", {})
239
387
 
240
- table = Table(show_header=True)
241
- table.add_column("Setting", style="cyan")
242
- table.add_column("Value", style="white")
388
+ def manage_config(args) -> int:
389
+ """Main entry point for configuration management commands.
243
390
 
244
- table.add_row("Enabled", str(rl_config.get("enabled", False)))
245
- table.add_row("Format", rl_config.get("format", "json"))
246
- table.add_row("Use Async", str(rl_config.get("use_async", True)))
247
- table.add_row(
248
- "Session Directory",
249
- rl_config.get("session_directory", ".claude-mpm/responses"),
250
- )
251
- table.add_row(
252
- "Compression", str(rl_config.get("enable_compression", False))
253
- )
391
+ This function maintains backward compatibility while using the new BaseCommand pattern.
392
+ """
393
+ command = ConfigCommand()
394
+ result = command.execute(args)
254
395
 
255
- console.print(table)
396
+ # Print result if not already handled
397
+ if hasattr(args, 'format') and args.format in ['json', 'yaml']:
398
+ command.print_result(result, args)
256
399
 
257
- return 0 if status["valid"] else 1
400
+ return result.exit_code
258
401
 
259
- except Exception as e:
260
- console.print(f"[red]Failed to get configuration status: {e}[/red]")
261
- logger.exception("Configuration status error")
262
- return 1
263
402
 
403
+ # Legacy function for backward compatibility
404
+ def validate_config(args) -> int:
405
+ """Legacy function for backward compatibility."""
406
+ command = ConfigCommand()
407
+ result = command.execute(args)
408
+ return result.exit_code
264
409
 
265
- def display_config_table(config_dict: dict, prefix: str = "") -> None:
266
- """Display configuration as a formatted table.
267
410
 
268
- Args:
269
- config_dict: Configuration dictionary
270
- prefix: Key prefix for nested values
271
- """
272
- table = Table(show_header=True, title="Configuration")
273
- table.add_column("Key", style="cyan", no_wrap=True)
274
- table.add_column("Value", style="white")
275
- table.add_column("Type", style="dim")
276
-
277
- def add_items(d: dict, prefix: str = ""):
278
- for key, value in d.items():
279
- full_key = f"{prefix}.{key}" if prefix else key
280
-
281
- if isinstance(value, dict) and value:
282
- # Add nested items
283
- add_items(value, full_key)
284
- else:
285
- # Add leaf value
286
- value_str = str(value)
287
- if len(value_str) > 50:
288
- value_str = value_str[:47] + "..."
411
+ def view_config(args) -> int:
412
+ """Legacy function for backward compatibility."""
413
+ command = ConfigCommand()
414
+ result = command.execute(args)
415
+ return result.exit_code
416
+
417
+
418
+ def show_config_status(args) -> int:
419
+ """Legacy function for backward compatibility."""
420
+ command = ConfigCommand()
421
+ result = command.execute(args)
422
+ return result.exit_code
289
423
 
290
- type_str = type(value).__name__
291
- table.add_row(full_key, value_str, type_str)
292
424
 
293
- add_items(config_dict)
294
- console.print(table)
425
+ def display_config_table(config_dict: dict, prefix: str = "") -> None:
426
+ """Legacy function for backward compatibility."""
427
+ command = ConfigCommand()
428
+ command._display_config_table(config_dict, prefix)