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
@@ -5,9 +5,12 @@ WHY: This module provides comprehensive ticket management functionality, allowin
5
5
  to create, view, update, and manage tickets through the CLI. It integrates with
6
6
  ai-trackdown-pytools for persistent ticket storage.
7
7
 
8
- DESIGN DECISION: We implement full CRUD operations plus search and workflow management
9
- to provide a complete ticket management system within the claude-mpm CLI. The commands
10
- mirror the scripts/ticket.py interface for consistency.
8
+ DESIGN DECISIONS:
9
+ - Use BaseCommand for consistent CLI patterns
10
+ - Leverage shared utilities for argument parsing and output formatting
11
+ - Maintain backward compatibility with existing ai-trackdown integration
12
+ - Support multiple output formats (json, yaml, table, text)
13
+ - Implement full CRUD operations plus search and workflow management
11
14
  """
12
15
 
13
16
  import json
@@ -17,14 +20,193 @@ from typing import Any, Dict, List, Optional
17
20
 
18
21
  from ...constants import TicketCommands
19
22
  from ...core.logger import get_logger
23
+ from ..shared import BaseCommand, CommandResult
24
+
25
+
26
+ class TicketsCommand(BaseCommand):
27
+ """Tickets command using shared utilities."""
28
+
29
+ def __init__(self):
30
+ super().__init__("tickets")
31
+
32
+ def validate_args(self, args) -> Optional[str]:
33
+ """Validate command arguments."""
34
+ if not hasattr(args, 'tickets_command') or not args.tickets_command:
35
+ return "No tickets subcommand specified"
36
+
37
+ valid_commands = [cmd.value for cmd in TicketCommands]
38
+ if args.tickets_command not in valid_commands:
39
+ return f"Unknown tickets command: {args.tickets_command}. Valid commands: {', '.join(valid_commands)}"
40
+
41
+ return None
42
+
43
+ def run(self, args) -> CommandResult:
44
+ """Execute the tickets command."""
45
+ try:
46
+ # Route to specific subcommand handlers
47
+ command_map = {
48
+ TicketCommands.CREATE.value: self._create_ticket,
49
+ TicketCommands.LIST.value: self._list_tickets,
50
+ TicketCommands.VIEW.value: self._view_ticket,
51
+ TicketCommands.UPDATE.value: self._update_ticket,
52
+ TicketCommands.CLOSE.value: self._close_ticket,
53
+ TicketCommands.DELETE.value: self._delete_ticket,
54
+ TicketCommands.SEARCH.value: self._search_tickets,
55
+ TicketCommands.COMMENT.value: self._add_comment,
56
+ TicketCommands.WORKFLOW.value: self._update_workflow,
57
+ }
58
+
59
+ if args.tickets_command in command_map:
60
+ return command_map[args.tickets_command](args)
61
+ else:
62
+ return CommandResult.error_result(f"Unknown tickets command: {args.tickets_command}")
63
+
64
+ except Exception as e:
65
+ self.logger.error(f"Error executing tickets command: {e}", exc_info=True)
66
+ return CommandResult.error_result(f"Error executing tickets command: {e}")
67
+
68
+ def _create_ticket(self, args) -> CommandResult:
69
+ """Create a new ticket."""
70
+ try:
71
+ exit_code = create_ticket_legacy(args)
72
+ if exit_code == 0:
73
+ return CommandResult.success_result("Ticket created successfully")
74
+ else:
75
+ return CommandResult.error_result("Failed to create ticket", exit_code=exit_code)
76
+ except Exception as e:
77
+ self.logger.error(f"Error creating ticket: {e}")
78
+ return CommandResult.error_result(f"Error creating ticket: {e}")
79
+
80
+ def _list_tickets(self, args) -> CommandResult:
81
+ """List tickets."""
82
+ try:
83
+ exit_code = list_tickets_legacy(args)
84
+ if exit_code == 0:
85
+ return CommandResult.success_result("Tickets listed successfully")
86
+ else:
87
+ return CommandResult.error_result("Failed to list tickets", exit_code=exit_code)
88
+ except Exception as e:
89
+ self.logger.error(f"Error listing tickets: {e}")
90
+ return CommandResult.error_result(f"Error listing tickets: {e}")
91
+
92
+ def _view_ticket(self, args) -> CommandResult:
93
+ """View a specific ticket."""
94
+ try:
95
+ exit_code = view_ticket_legacy(args)
96
+ if exit_code == 0:
97
+ return CommandResult.success_result("Ticket viewed successfully")
98
+ else:
99
+ return CommandResult.error_result("Failed to view ticket", exit_code=exit_code)
100
+ except Exception as e:
101
+ self.logger.error(f"Error viewing ticket: {e}")
102
+ return CommandResult.error_result(f"Error viewing ticket: {e}")
103
+
104
+ def _update_ticket(self, args) -> CommandResult:
105
+ """Update a ticket."""
106
+ try:
107
+ exit_code = update_ticket_legacy(args)
108
+ if exit_code == 0:
109
+ return CommandResult.success_result("Ticket updated successfully")
110
+ else:
111
+ return CommandResult.error_result("Failed to update ticket", exit_code=exit_code)
112
+ except Exception as e:
113
+ self.logger.error(f"Error updating ticket: {e}")
114
+ return CommandResult.error_result(f"Error updating ticket: {e}")
115
+
116
+ def _close_ticket(self, args) -> CommandResult:
117
+ """Close a ticket."""
118
+ try:
119
+ exit_code = close_ticket_legacy(args)
120
+ if exit_code == 0:
121
+ return CommandResult.success_result("Ticket closed successfully")
122
+ else:
123
+ return CommandResult.error_result("Failed to close ticket", exit_code=exit_code)
124
+ except Exception as e:
125
+ self.logger.error(f"Error closing ticket: {e}")
126
+ return CommandResult.error_result(f"Error closing ticket: {e}")
127
+
128
+ def _delete_ticket(self, args) -> CommandResult:
129
+ """Delete a ticket."""
130
+ try:
131
+ exit_code = delete_ticket_legacy(args)
132
+ if exit_code == 0:
133
+ return CommandResult.success_result("Ticket deleted successfully")
134
+ else:
135
+ return CommandResult.error_result("Failed to delete ticket", exit_code=exit_code)
136
+ except Exception as e:
137
+ self.logger.error(f"Error deleting ticket: {e}")
138
+ return CommandResult.error_result(f"Error deleting ticket: {e}")
139
+
140
+ def _search_tickets(self, args) -> CommandResult:
141
+ """Search tickets."""
142
+ try:
143
+ exit_code = search_tickets_legacy(args)
144
+ if exit_code == 0:
145
+ return CommandResult.success_result("Tickets searched successfully")
146
+ else:
147
+ return CommandResult.error_result("Failed to search tickets", exit_code=exit_code)
148
+ except Exception as e:
149
+ self.logger.error(f"Error searching tickets: {e}")
150
+ return CommandResult.error_result(f"Error searching tickets: {e}")
151
+
152
+ def _add_comment(self, args) -> CommandResult:
153
+ """Add a comment to a ticket."""
154
+ try:
155
+ exit_code = add_comment_legacy(args)
156
+ if exit_code == 0:
157
+ return CommandResult.success_result("Comment added successfully")
158
+ else:
159
+ return CommandResult.error_result("Failed to add comment", exit_code=exit_code)
160
+ except Exception as e:
161
+ self.logger.error(f"Error adding comment: {e}")
162
+ return CommandResult.error_result(f"Error adding comment: {e}")
163
+
164
+ def _update_workflow(self, args) -> CommandResult:
165
+ """Update workflow state."""
166
+ try:
167
+ exit_code = update_workflow_legacy(args)
168
+ if exit_code == 0:
169
+ return CommandResult.success_result("Workflow updated successfully")
170
+ else:
171
+ return CommandResult.error_result("Failed to update workflow", exit_code=exit_code)
172
+ except Exception as e:
173
+ self.logger.error(f"Error updating workflow: {e}")
174
+ return CommandResult.error_result(f"Error updating workflow: {e}")
20
175
 
21
176
 
22
177
  def manage_tickets(args):
23
178
  """
24
- Main ticket command dispatcher.
179
+ Main entry point for tickets command.
180
+
181
+ This function maintains backward compatibility while using the new BaseCommand pattern.
182
+ """
183
+ command = TicketsCommand()
184
+ result = command.execute(args)
25
185
 
26
- WHY: This function routes ticket subcommands to their appropriate handlers,
27
- providing a single entry point for all ticket-related operations.
186
+ # Print result if structured output format is requested
187
+ if hasattr(args, 'format') and args.format in ['json', 'yaml']:
188
+ command.print_result(result, args)
189
+
190
+ return result.exit_code
191
+
192
+
193
+ def list_tickets(args):
194
+ """
195
+ Compatibility function for list_tickets.
196
+
197
+ This maintains backward compatibility for imports while using the new TicketsCommand pattern.
198
+ """
199
+ # Create a tickets command and execute the list subcommand
200
+ args.tickets_command = TicketCommands.LIST.value
201
+ return manage_tickets(args)
202
+
203
+
204
+ def manage_tickets_legacy(args):
205
+ """
206
+ Legacy ticket command dispatcher.
207
+
208
+ WHY: This contains the original manage_tickets logic, preserved during migration
209
+ to BaseCommand pattern. Will be gradually refactored into the TicketsCommand class.
28
210
 
29
211
  DESIGN DECISION: We use a subcommand pattern similar to git, allowing for
30
212
  intuitive command structure like 'claude-mpm tickets create "title"'.
@@ -49,15 +231,15 @@ def manage_tickets(args):
49
231
 
50
232
  # Map subcommands to handler functions
51
233
  handlers = {
52
- TicketCommands.CREATE.value: create_ticket,
53
- TicketCommands.LIST.value: list_tickets,
54
- TicketCommands.VIEW.value: view_ticket,
55
- TicketCommands.UPDATE.value: update_ticket,
56
- TicketCommands.CLOSE.value: close_ticket,
57
- TicketCommands.DELETE.value: delete_ticket,
58
- TicketCommands.SEARCH.value: search_tickets,
59
- TicketCommands.COMMENT.value: add_comment,
60
- TicketCommands.WORKFLOW.value: update_workflow,
234
+ TicketCommands.CREATE.value: create_ticket_legacy,
235
+ TicketCommands.LIST.value: list_tickets_legacy,
236
+ TicketCommands.VIEW.value: view_ticket_legacy,
237
+ TicketCommands.UPDATE.value: update_ticket_legacy,
238
+ TicketCommands.CLOSE.value: close_ticket_legacy,
239
+ TicketCommands.DELETE.value: delete_ticket_legacy,
240
+ TicketCommands.SEARCH.value: search_tickets_legacy,
241
+ TicketCommands.COMMENT.value: add_comment_legacy,
242
+ TicketCommands.WORKFLOW.value: update_workflow_legacy,
61
243
  }
62
244
 
63
245
  # Execute the appropriate handler
@@ -80,7 +262,7 @@ def manage_tickets(args):
80
262
  return 1
81
263
 
82
264
 
83
- def create_ticket(args):
265
+ def create_ticket_legacy(args):
84
266
  """
85
267
  Create a new ticket.
86
268
 
@@ -140,7 +322,7 @@ def create_ticket(args):
140
322
  return 1
141
323
 
142
324
 
143
- def list_tickets(args):
325
+ def list_tickets_legacy(args):
144
326
  """
145
327
  List recent tickets with optional filtering.
146
328
 
@@ -306,7 +488,7 @@ def list_tickets(args):
306
488
  return 1
307
489
 
308
490
 
309
- def view_ticket(args):
491
+ def view_ticket_legacy(args):
310
492
  """
311
493
  View a specific ticket in detail.
312
494
 
@@ -379,7 +561,7 @@ def view_ticket(args):
379
561
  return 0
380
562
 
381
563
 
382
- def update_ticket(args):
564
+ def update_ticket_legacy(args):
383
565
  """
384
566
  Update a ticket's properties.
385
567
 
@@ -470,7 +652,7 @@ def update_ticket(args):
470
652
  return 1
471
653
 
472
654
 
473
- def close_ticket(args):
655
+ def close_ticket_legacy(args):
474
656
  """
475
657
  Close a ticket.
476
658
 
@@ -521,7 +703,7 @@ def close_ticket(args):
521
703
  return 1
522
704
 
523
705
 
524
- def delete_ticket(args):
706
+ def delete_ticket_legacy(args):
525
707
  """
526
708
  Delete a ticket.
527
709
 
@@ -592,7 +774,7 @@ def delete_ticket(args):
592
774
  return 1
593
775
 
594
776
 
595
- def search_tickets(args):
777
+ def search_tickets_legacy(args):
596
778
  """
597
779
  Search tickets by query string.
598
780
 
@@ -680,7 +862,7 @@ def search_tickets(args):
680
862
  return 0
681
863
 
682
864
 
683
- def add_comment(args):
865
+ def add_comment_legacy(args):
684
866
  """
685
867
  Add a comment to a ticket.
686
868
 
@@ -719,7 +901,7 @@ def add_comment(args):
719
901
  return 1
720
902
 
721
903
 
722
- def update_workflow(args):
904
+ def update_workflow_legacy(args):
723
905
  """
724
906
  Update ticket workflow state.
725
907
 
@@ -171,5 +171,8 @@ def add_mcp_subparser(subparsers) -> argparse.ArgumentParser:
171
171
  server_mcp_parser.add_argument(
172
172
  "--test", action="store_true", help="Run in test mode with debug output"
173
173
  )
174
+ server_mcp_parser.add_argument(
175
+ "--instructions", action="store_true", help="Show setup instructions for Claude Desktop"
176
+ )
174
177
 
175
178
  return mcp_parser
@@ -0,0 +1,40 @@
1
+ """
2
+ Shared CLI utilities for claude-mpm.
3
+
4
+ This module provides common utilities to reduce code duplication across CLI commands.
5
+ """
6
+
7
+ from .argument_patterns import (
8
+ CommonArguments,
9
+ add_agent_arguments,
10
+ add_common_arguments,
11
+ add_config_arguments,
12
+ add_logging_arguments,
13
+ add_memory_arguments,
14
+ add_output_arguments,
15
+ )
16
+ from .command_base import AgentCommand, BaseCommand, CommandResult, MemoryCommand
17
+ from .error_handling import CLIErrorHandler, handle_cli_errors
18
+ from .output_formatters import OutputFormatter, format_output
19
+
20
+ __all__ = [
21
+ # Argument patterns
22
+ "CommonArguments",
23
+ "add_agent_arguments",
24
+ "add_common_arguments",
25
+ "add_config_arguments",
26
+ "add_logging_arguments",
27
+ "add_memory_arguments",
28
+ "add_output_arguments",
29
+ # Command base
30
+ "AgentCommand",
31
+ "BaseCommand",
32
+ "CommandResult",
33
+ "MemoryCommand",
34
+ # Error handling
35
+ "CLIErrorHandler",
36
+ "handle_cli_errors",
37
+ # Output formatting
38
+ "OutputFormatter",
39
+ "format_output",
40
+ ]
@@ -0,0 +1,212 @@
1
+ """
2
+ Common CLI argument patterns to reduce duplication.
3
+
4
+ This module provides reusable argument definitions that are commonly used
5
+ across multiple CLI commands.
6
+ """
7
+
8
+ import argparse
9
+ from pathlib import Path
10
+ from typing import Any, Dict, List, Optional
11
+
12
+
13
+ class CommonArguments:
14
+ """Registry of common argument patterns used across CLI commands."""
15
+
16
+ # Logging arguments
17
+ VERBOSE = {
18
+ "flags": ["-v", "--verbose"],
19
+ "action": "store_true",
20
+ "help": "Enable verbose output"
21
+ }
22
+
23
+ QUIET = {
24
+ "flags": ["-q", "--quiet"],
25
+ "action": "store_true",
26
+ "help": "Suppress non-error output"
27
+ }
28
+
29
+ DEBUG = {
30
+ "flags": ["--debug"],
31
+ "action": "store_true",
32
+ "help": "Enable debug logging"
33
+ }
34
+
35
+ # Configuration arguments
36
+ CONFIG_FILE = {
37
+ "flags": ["-c", "--config"],
38
+ "type": Path,
39
+ "help": "Path to configuration file"
40
+ }
41
+
42
+ CONFIG_DIR = {
43
+ "flags": ["--config-dir"],
44
+ "type": Path,
45
+ "help": "Configuration directory path"
46
+ }
47
+
48
+ # Output arguments
49
+ OUTPUT_FORMAT = {
50
+ "flags": ["-f", "--format"],
51
+ "choices": ["json", "yaml", "table", "text"],
52
+ "default": "text",
53
+ "help": "Output format"
54
+ }
55
+
56
+ OUTPUT_FILE = {
57
+ "flags": ["-o", "--output"],
58
+ "type": Path,
59
+ "help": "Output file path"
60
+ }
61
+
62
+ # Common flags
63
+ FORCE = {
64
+ "flags": ["--force"],
65
+ "action": "store_true",
66
+ "help": "Force operation without confirmation"
67
+ }
68
+
69
+ DRY_RUN = {
70
+ "flags": ["--dry-run"],
71
+ "action": "store_true",
72
+ "help": "Show what would be done without executing"
73
+ }
74
+
75
+ # Agent-related arguments
76
+ AGENT_NAME = {
77
+ "flags": ["--agent"],
78
+ "help": "Agent name or pattern"
79
+ }
80
+
81
+ AGENT_DIR = {
82
+ "flags": ["--agent-dir"],
83
+ "type": Path,
84
+ "help": "Agent directory path"
85
+ }
86
+
87
+ # Memory-related arguments
88
+ MEMORY_DIR = {
89
+ "flags": ["--memory-dir"],
90
+ "type": Path,
91
+ "help": "Memory directory path"
92
+ }
93
+
94
+
95
+ def add_argument_from_pattern(parser: argparse.ArgumentParser, pattern: Dict[str, Any]) -> None:
96
+ """Add an argument to parser from a pattern definition."""
97
+ flags = pattern.pop("flags")
98
+ parser.add_argument(*flags, **pattern)
99
+
100
+
101
+ def add_common_arguments(parser: argparse.ArgumentParser,
102
+ include: Optional[List[str]] = None,
103
+ exclude: Optional[List[str]] = None) -> None:
104
+ """
105
+ Add common arguments to a parser.
106
+
107
+ Args:
108
+ parser: ArgumentParser to add arguments to
109
+ include: List of argument names to include (if None, includes all)
110
+ exclude: List of argument names to exclude
111
+ """
112
+ # Default common arguments
113
+ common_args = ["verbose", "quiet", "debug", "config_file", "output_format"]
114
+
115
+ if include is not None:
116
+ common_args = [arg for arg in common_args if arg in include]
117
+
118
+ if exclude is not None:
119
+ common_args = [arg for arg in common_args if arg not in exclude]
120
+
121
+ # Map argument names to patterns
122
+ arg_patterns = {
123
+ "verbose": CommonArguments.VERBOSE.copy(),
124
+ "quiet": CommonArguments.QUIET.copy(),
125
+ "debug": CommonArguments.DEBUG.copy(),
126
+ "config_file": CommonArguments.CONFIG_FILE.copy(),
127
+ "output_format": CommonArguments.OUTPUT_FORMAT.copy(),
128
+ "force": CommonArguments.FORCE.copy(),
129
+ "dry_run": CommonArguments.DRY_RUN.copy(),
130
+ }
131
+
132
+ for arg_name in common_args:
133
+ if arg_name in arg_patterns:
134
+ add_argument_from_pattern(parser, arg_patterns[arg_name])
135
+
136
+
137
+ def add_logging_arguments(parser: argparse.ArgumentParser) -> None:
138
+ """Add logging-related arguments."""
139
+ group = parser.add_argument_group("logging options")
140
+
141
+ patterns = [
142
+ CommonArguments.VERBOSE.copy(),
143
+ CommonArguments.QUIET.copy(),
144
+ CommonArguments.DEBUG.copy()
145
+ ]
146
+
147
+ for pattern in patterns:
148
+ add_argument_from_pattern(group, pattern)
149
+
150
+
151
+ def add_config_arguments(parser: argparse.ArgumentParser) -> None:
152
+ """Add configuration-related arguments."""
153
+ group = parser.add_argument_group("configuration options")
154
+
155
+ patterns = [
156
+ CommonArguments.CONFIG_FILE.copy(),
157
+ CommonArguments.CONFIG_DIR.copy()
158
+ ]
159
+
160
+ for pattern in patterns:
161
+ add_argument_from_pattern(group, pattern)
162
+
163
+
164
+ def add_output_arguments(parser: argparse.ArgumentParser) -> None:
165
+ """Add output-related arguments."""
166
+ group = parser.add_argument_group("output options")
167
+
168
+ patterns = [
169
+ CommonArguments.OUTPUT_FORMAT.copy(),
170
+ CommonArguments.OUTPUT_FILE.copy()
171
+ ]
172
+
173
+ for pattern in patterns:
174
+ add_argument_from_pattern(group, pattern)
175
+
176
+
177
+ def add_agent_arguments(parser: argparse.ArgumentParser) -> None:
178
+ """Add agent-related arguments."""
179
+ group = parser.add_argument_group("agent options")
180
+
181
+ patterns = [
182
+ CommonArguments.AGENT_NAME.copy(),
183
+ CommonArguments.AGENT_DIR.copy()
184
+ ]
185
+
186
+ for pattern in patterns:
187
+ add_argument_from_pattern(group, pattern)
188
+
189
+
190
+ def add_memory_arguments(parser: argparse.ArgumentParser) -> None:
191
+ """Add memory-related arguments."""
192
+ group = parser.add_argument_group("memory options")
193
+
194
+ patterns = [
195
+ CommonArguments.MEMORY_DIR.copy()
196
+ ]
197
+
198
+ for pattern in patterns:
199
+ add_argument_from_pattern(group, pattern)
200
+
201
+
202
+ def add_operation_arguments(parser: argparse.ArgumentParser) -> None:
203
+ """Add operation control arguments."""
204
+ group = parser.add_argument_group("operation options")
205
+
206
+ patterns = [
207
+ CommonArguments.FORCE.copy(),
208
+ CommonArguments.DRY_RUN.copy()
209
+ ]
210
+
211
+ for pattern in patterns:
212
+ add_argument_from_pattern(group, pattern)