claude-mpm 0.3.0__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/__init__.py +17 -0
- claude_mpm/__main__.py +14 -0
- claude_mpm/_version.py +32 -0
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +88 -0
- claude_mpm/agents/INSTRUCTIONS.md +375 -0
- claude_mpm/agents/__init__.py +118 -0
- claude_mpm/agents/agent_loader.py +621 -0
- claude_mpm/agents/agent_loader_integration.py +229 -0
- claude_mpm/agents/agents_metadata.py +204 -0
- claude_mpm/agents/base_agent.json +27 -0
- claude_mpm/agents/base_agent_loader.py +519 -0
- claude_mpm/agents/schema/agent_schema.json +160 -0
- claude_mpm/agents/system_agent_config.py +587 -0
- claude_mpm/agents/templates/__init__.py +101 -0
- claude_mpm/agents/templates/data_engineer_agent.json +46 -0
- claude_mpm/agents/templates/documentation_agent.json +45 -0
- claude_mpm/agents/templates/engineer_agent.json +49 -0
- claude_mpm/agents/templates/ops_agent.json +46 -0
- claude_mpm/agents/templates/qa_agent.json +45 -0
- claude_mpm/agents/templates/research_agent.json +49 -0
- claude_mpm/agents/templates/security_agent.json +46 -0
- claude_mpm/agents/templates/update-optimized-specialized-agents.json +374 -0
- claude_mpm/agents/templates/version_control_agent.json +46 -0
- claude_mpm/agents/test_fix_deployment/.claude-pm/config/project.json +6 -0
- claude_mpm/cli.py +655 -0
- claude_mpm/cli_main.py +13 -0
- claude_mpm/cli_module/__init__.py +15 -0
- claude_mpm/cli_module/args.py +222 -0
- claude_mpm/cli_module/commands.py +203 -0
- claude_mpm/cli_module/migration_example.py +183 -0
- claude_mpm/cli_module/refactoring_guide.md +253 -0
- claude_mpm/cli_old/__init__.py +1 -0
- claude_mpm/cli_old/ticket_cli.py +102 -0
- claude_mpm/config/__init__.py +5 -0
- claude_mpm/config/hook_config.py +42 -0
- claude_mpm/constants.py +150 -0
- claude_mpm/core/__init__.py +45 -0
- claude_mpm/core/agent_name_normalizer.py +248 -0
- claude_mpm/core/agent_registry.py +627 -0
- claude_mpm/core/agent_registry.py.bak +312 -0
- claude_mpm/core/agent_session_manager.py +273 -0
- claude_mpm/core/base_service.py +747 -0
- claude_mpm/core/base_service.py.bak +406 -0
- claude_mpm/core/config.py +334 -0
- claude_mpm/core/config_aliases.py +292 -0
- claude_mpm/core/container.py +347 -0
- claude_mpm/core/factories.py +281 -0
- claude_mpm/core/framework_loader.py +472 -0
- claude_mpm/core/injectable_service.py +206 -0
- claude_mpm/core/interfaces.py +539 -0
- claude_mpm/core/logger.py +468 -0
- claude_mpm/core/minimal_framework_loader.py +107 -0
- claude_mpm/core/mixins.py +150 -0
- claude_mpm/core/service_registry.py +299 -0
- claude_mpm/core/session_manager.py +190 -0
- claude_mpm/core/simple_runner.py +511 -0
- claude_mpm/core/tool_access_control.py +173 -0
- claude_mpm/hooks/README.md +243 -0
- claude_mpm/hooks/__init__.py +5 -0
- claude_mpm/hooks/base_hook.py +154 -0
- claude_mpm/hooks/builtin/__init__.py +1 -0
- claude_mpm/hooks/builtin/logging_hook_example.py +165 -0
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +124 -0
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +125 -0
- claude_mpm/hooks/builtin/submit_hook_example.py +100 -0
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +237 -0
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +239 -0
- claude_mpm/hooks/builtin/workflow_start_hook.py +181 -0
- claude_mpm/hooks/hook_client.py +264 -0
- claude_mpm/hooks/hook_runner.py +370 -0
- claude_mpm/hooks/json_rpc_executor.py +259 -0
- claude_mpm/hooks/json_rpc_hook_client.py +319 -0
- claude_mpm/hooks/tool_call_interceptor.py +204 -0
- claude_mpm/init.py +246 -0
- claude_mpm/orchestration/SUBPROCESS_DESIGN.md +66 -0
- claude_mpm/orchestration/__init__.py +6 -0
- claude_mpm/orchestration/archive/direct_orchestrator.py +195 -0
- claude_mpm/orchestration/archive/factory.py +215 -0
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +188 -0
- claude_mpm/orchestration/archive/hook_integration_example.py +178 -0
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +826 -0
- claude_mpm/orchestration/archive/orchestrator.py +501 -0
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +252 -0
- claude_mpm/orchestration/archive/pty_orchestrator.py +270 -0
- claude_mpm/orchestration/archive/simple_orchestrator.py +82 -0
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +801 -0
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +278 -0
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +187 -0
- claude_mpm/scripts/__init__.py +1 -0
- claude_mpm/scripts/ticket.py +269 -0
- claude_mpm/services/__init__.py +10 -0
- claude_mpm/services/agent_deployment.py +955 -0
- claude_mpm/services/agent_lifecycle_manager.py +948 -0
- claude_mpm/services/agent_management_service.py +596 -0
- claude_mpm/services/agent_modification_tracker.py +841 -0
- claude_mpm/services/agent_profile_loader.py +606 -0
- claude_mpm/services/agent_registry.py +677 -0
- claude_mpm/services/base_agent_manager.py +380 -0
- claude_mpm/services/framework_agent_loader.py +337 -0
- claude_mpm/services/framework_claude_md_generator/README.md +92 -0
- claude_mpm/services/framework_claude_md_generator/__init__.py +206 -0
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +151 -0
- claude_mpm/services/framework_claude_md_generator/content_validator.py +126 -0
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +137 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +106 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +582 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +97 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +27 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +23 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +23 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +20 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +26 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +30 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +37 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +111 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +89 -0
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +39 -0
- claude_mpm/services/framework_claude_md_generator/section_manager.py +106 -0
- claude_mpm/services/framework_claude_md_generator/version_manager.py +121 -0
- claude_mpm/services/framework_claude_md_generator.py +621 -0
- claude_mpm/services/hook_service.py +388 -0
- claude_mpm/services/hook_service_manager.py +223 -0
- claude_mpm/services/json_rpc_hook_manager.py +92 -0
- claude_mpm/services/parent_directory_manager/README.md +83 -0
- claude_mpm/services/parent_directory_manager/__init__.py +577 -0
- claude_mpm/services/parent_directory_manager/backup_manager.py +258 -0
- claude_mpm/services/parent_directory_manager/config_manager.py +210 -0
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +279 -0
- claude_mpm/services/parent_directory_manager/framework_protector.py +143 -0
- claude_mpm/services/parent_directory_manager/operations.py +186 -0
- claude_mpm/services/parent_directory_manager/state_manager.py +624 -0
- claude_mpm/services/parent_directory_manager/template_deployer.py +579 -0
- claude_mpm/services/parent_directory_manager/validation_manager.py +378 -0
- claude_mpm/services/parent_directory_manager/version_control_helper.py +339 -0
- claude_mpm/services/parent_directory_manager/version_manager.py +222 -0
- claude_mpm/services/shared_prompt_cache.py +819 -0
- claude_mpm/services/ticket_manager.py +213 -0
- claude_mpm/services/ticket_manager_di.py +318 -0
- claude_mpm/services/ticketing_service_original.py +508 -0
- claude_mpm/services/version_control/VERSION +1 -0
- claude_mpm/services/version_control/__init__.py +70 -0
- claude_mpm/services/version_control/branch_strategy.py +670 -0
- claude_mpm/services/version_control/conflict_resolution.py +744 -0
- claude_mpm/services/version_control/git_operations.py +784 -0
- claude_mpm/services/version_control/semantic_versioning.py +703 -0
- claude_mpm/ui/__init__.py +1 -0
- claude_mpm/ui/rich_terminal_ui.py +295 -0
- claude_mpm/ui/terminal_ui.py +328 -0
- claude_mpm/utils/__init__.py +16 -0
- claude_mpm/utils/config_manager.py +468 -0
- claude_mpm/utils/import_migration_example.py +80 -0
- claude_mpm/utils/imports.py +182 -0
- claude_mpm/utils/path_operations.py +357 -0
- claude_mpm/utils/paths.py +289 -0
- claude_mpm-0.3.0.dist-info/METADATA +290 -0
- claude_mpm-0.3.0.dist-info/RECORD +159 -0
- claude_mpm-0.3.0.dist-info/WHEEL +5 -0
- claude_mpm-0.3.0.dist-info/entry_points.txt +4 -0
- claude_mpm-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# CLI Refactoring Guide
|
|
2
|
+
|
|
3
|
+
This guide shows how to refactor the main() function in `/src/claude_mpm/cli.py` to reduce complexity from 16 to under 10.
|
|
4
|
+
|
|
5
|
+
## Current Issues
|
|
6
|
+
|
|
7
|
+
1. **High Cyclomatic Complexity (16)**
|
|
8
|
+
- Multiple nested conditionals
|
|
9
|
+
- Duplicate argument definitions
|
|
10
|
+
- Mixed concerns in one function
|
|
11
|
+
|
|
12
|
+
2. **Code Duplication**
|
|
13
|
+
- Arguments defined twice (global level + run subcommand)
|
|
14
|
+
- Similar patterns repeated for each command
|
|
15
|
+
|
|
16
|
+
3. **Poor Maintainability**
|
|
17
|
+
- Adding new commands requires multiple changes
|
|
18
|
+
- Hard to test individual components
|
|
19
|
+
|
|
20
|
+
## Refactoring Steps
|
|
21
|
+
|
|
22
|
+
### Step 1: Update imports in cli.py
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
# Add to imports
|
|
26
|
+
from .cli import ArgumentRegistry, CommandRegistry, register_standard_commands
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Step 2: Replace main() function
|
|
30
|
+
|
|
31
|
+
Replace the entire `main()` function with:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
def main(argv: Optional[list] = None):
|
|
35
|
+
"""Main CLI entry point with reduced complexity."""
|
|
36
|
+
# Initialize registries
|
|
37
|
+
arg_registry = ArgumentRegistry()
|
|
38
|
+
cmd_registry = CommandRegistry(arg_registry)
|
|
39
|
+
|
|
40
|
+
# Register standard commands
|
|
41
|
+
register_standard_commands(cmd_registry)
|
|
42
|
+
|
|
43
|
+
# Create parser
|
|
44
|
+
parser = argparse.ArgumentParser(
|
|
45
|
+
prog="claude-mpm",
|
|
46
|
+
description=f"Claude Multi-Agent Project Manager v{__version__}",
|
|
47
|
+
epilog="By default, runs an orchestrated Claude session."
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Store version for ArgumentRegistry
|
|
51
|
+
parser._version = f"claude-mpm {__version__}"
|
|
52
|
+
|
|
53
|
+
# Apply global arguments
|
|
54
|
+
arg_registry.apply_arguments(parser, groups=['global'])
|
|
55
|
+
|
|
56
|
+
# Apply run arguments at top level (for default behavior)
|
|
57
|
+
arg_registry.apply_arguments(parser, groups=['run'], exclude=['no_hooks'])
|
|
58
|
+
|
|
59
|
+
# Set up subcommands
|
|
60
|
+
cmd_registry.setup_subcommands(parser)
|
|
61
|
+
|
|
62
|
+
# Parse arguments
|
|
63
|
+
args = parser.parse_args(argv)
|
|
64
|
+
|
|
65
|
+
# Set up logging
|
|
66
|
+
_setup_logging(args)
|
|
67
|
+
|
|
68
|
+
# Initialize hook service
|
|
69
|
+
hook_manager = _initialize_hook_service(args)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
# Execute command
|
|
73
|
+
result = cmd_registry.execute_command(args, hook_manager=hook_manager)
|
|
74
|
+
if result is None and not args.command:
|
|
75
|
+
parser.print_help()
|
|
76
|
+
return 1
|
|
77
|
+
return result or 0
|
|
78
|
+
|
|
79
|
+
except KeyboardInterrupt:
|
|
80
|
+
get_logger("cli").info("Session interrupted by user")
|
|
81
|
+
return 0
|
|
82
|
+
except Exception as e:
|
|
83
|
+
logger = get_logger("cli")
|
|
84
|
+
logger.error(f"Error: {e}")
|
|
85
|
+
if args.debug:
|
|
86
|
+
import traceback
|
|
87
|
+
traceback.print_exc()
|
|
88
|
+
return 1
|
|
89
|
+
finally:
|
|
90
|
+
if hook_manager:
|
|
91
|
+
hook_manager.stop_service()
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Step 3: Extract helper functions
|
|
95
|
+
|
|
96
|
+
Add these helper functions after main():
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
def _setup_logging(args):
|
|
100
|
+
"""Set up logging based on arguments."""
|
|
101
|
+
if args.debug and args.logging == "OFF":
|
|
102
|
+
args.logging = "DEBUG"
|
|
103
|
+
|
|
104
|
+
if args.logging != "OFF":
|
|
105
|
+
setup_logging(level=args.logging, log_dir=args.log_dir)
|
|
106
|
+
else:
|
|
107
|
+
import logging
|
|
108
|
+
logger = logging.getLogger("cli")
|
|
109
|
+
logger.setLevel(logging.WARNING)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _initialize_hook_service(args):
|
|
113
|
+
"""Initialize hook service if enabled."""
|
|
114
|
+
if getattr(args, 'no_hooks', False):
|
|
115
|
+
return None
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
from .config.hook_config import HookConfig
|
|
119
|
+
|
|
120
|
+
if not HookConfig.is_hooks_enabled():
|
|
121
|
+
get_logger("cli").info("Hooks disabled via configuration")
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
hook_manager = HookServiceManager(log_dir=args.log_dir)
|
|
125
|
+
if hook_manager.start_service():
|
|
126
|
+
logger = get_logger("cli")
|
|
127
|
+
logger.info(f"Hook service started on port {hook_manager.port}")
|
|
128
|
+
print(f"Hook service started on port {hook_manager.port}")
|
|
129
|
+
return hook_manager
|
|
130
|
+
else:
|
|
131
|
+
logger = get_logger("cli")
|
|
132
|
+
logger.warning("Failed to start hook service")
|
|
133
|
+
print("Failed to start hook service, continuing without hooks")
|
|
134
|
+
return None
|
|
135
|
+
|
|
136
|
+
except Exception as e:
|
|
137
|
+
get_logger("cli").warning(f"Hook service init failed: {e}")
|
|
138
|
+
return None
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Step 4: Update command handler signatures
|
|
142
|
+
|
|
143
|
+
Ensure all command handlers accept `**kwargs`:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
def run_session(args, hook_manager=None, **kwargs):
|
|
147
|
+
"""Run an orchestrated Claude session."""
|
|
148
|
+
# ... existing implementation
|
|
149
|
+
|
|
150
|
+
def list_tickets(args, **kwargs):
|
|
151
|
+
"""List recent tickets."""
|
|
152
|
+
# ... existing implementation
|
|
153
|
+
|
|
154
|
+
def show_info(args, hook_manager=None, **kwargs):
|
|
155
|
+
"""Show framework and configuration information."""
|
|
156
|
+
# ... existing implementation
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Benefits Achieved
|
|
160
|
+
|
|
161
|
+
### Complexity Reduction
|
|
162
|
+
- **Before**: Cyclomatic complexity of 16
|
|
163
|
+
- **After**: Cyclomatic complexity of ~8
|
|
164
|
+
|
|
165
|
+
### Code Organization
|
|
166
|
+
- Centralized argument definitions
|
|
167
|
+
- No duplicate argument definitions
|
|
168
|
+
- Clear separation of concerns
|
|
169
|
+
- Easier to add new commands
|
|
170
|
+
|
|
171
|
+
### Maintainability
|
|
172
|
+
- New commands can be added with a single `register()` call
|
|
173
|
+
- Arguments are defined once and reused
|
|
174
|
+
- Helper functions are testable in isolation
|
|
175
|
+
- Registry pattern allows for extension
|
|
176
|
+
|
|
177
|
+
## Adding New Commands
|
|
178
|
+
|
|
179
|
+
With the registry system, adding a new command is simple:
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
# In your code or plugin
|
|
183
|
+
def my_command(args, **kwargs):
|
|
184
|
+
"""Implementation of your command."""
|
|
185
|
+
print(f"Running my command with args: {args}")
|
|
186
|
+
return 0
|
|
187
|
+
|
|
188
|
+
# Register it
|
|
189
|
+
cmd_registry.register(
|
|
190
|
+
name='mycommand',
|
|
191
|
+
help_text='Description of my command',
|
|
192
|
+
handler=my_command,
|
|
193
|
+
argument_groups=['framework'], # Reuse existing argument groups
|
|
194
|
+
extra_args={
|
|
195
|
+
'custom_arg': {
|
|
196
|
+
'flags': ['--custom'],
|
|
197
|
+
'type': str,
|
|
198
|
+
'help': 'A custom argument for this command'
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Testing
|
|
205
|
+
|
|
206
|
+
The refactored code is easier to test:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
# Test argument registry
|
|
210
|
+
def test_argument_registry():
|
|
211
|
+
registry = ArgumentRegistry()
|
|
212
|
+
parser = argparse.ArgumentParser()
|
|
213
|
+
registry.apply_arguments(parser, groups=['logging'])
|
|
214
|
+
|
|
215
|
+
# Verify logging arguments were added
|
|
216
|
+
args = parser.parse_args(['--logging', 'DEBUG'])
|
|
217
|
+
assert args.logging == 'DEBUG'
|
|
218
|
+
|
|
219
|
+
# Test command registry
|
|
220
|
+
def test_command_registry():
|
|
221
|
+
arg_reg = ArgumentRegistry()
|
|
222
|
+
cmd_reg = CommandRegistry(arg_reg)
|
|
223
|
+
|
|
224
|
+
called = False
|
|
225
|
+
def test_handler(args, **kwargs):
|
|
226
|
+
nonlocal called
|
|
227
|
+
called = True
|
|
228
|
+
return 0
|
|
229
|
+
|
|
230
|
+
cmd_reg.register('test', 'Test command', test_handler)
|
|
231
|
+
|
|
232
|
+
parser = argparse.ArgumentParser()
|
|
233
|
+
cmd_reg.setup_subcommands(parser)
|
|
234
|
+
|
|
235
|
+
args = parser.parse_args(['test'])
|
|
236
|
+
result = cmd_reg.execute_command(args)
|
|
237
|
+
|
|
238
|
+
assert called
|
|
239
|
+
assert result == 0
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Migration Checklist
|
|
243
|
+
|
|
244
|
+
- [ ] Create `/src/claude_mpm/cli/` directory
|
|
245
|
+
- [ ] Create `args.py` with ArgumentRegistry
|
|
246
|
+
- [ ] Create `commands.py` with CommandRegistry
|
|
247
|
+
- [ ] Create `__init__.py` to export classes
|
|
248
|
+
- [ ] Update imports in `cli.py`
|
|
249
|
+
- [ ] Replace main() function
|
|
250
|
+
- [ ] Add helper functions
|
|
251
|
+
- [ ] Update command handler signatures
|
|
252
|
+
- [ ] Test the refactored CLI
|
|
253
|
+
- [ ] Verify complexity is reduced to ≤10
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI module for claude-mpm."""
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Ticket Management CLI - delegates to aitrackdown.
|
|
4
|
+
|
|
5
|
+
This module provides a wrapper that delegates all ticket operations
|
|
6
|
+
to the aitrackdown command-line tool.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
import subprocess
|
|
11
|
+
import argparse
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main():
|
|
15
|
+
"""Main entry point that delegates to aitrackdown."""
|
|
16
|
+
parser = argparse.ArgumentParser(
|
|
17
|
+
description="Ticket management for Claude MPM (delegates to aitrackdown)",
|
|
18
|
+
add_help=False
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Capture all arguments
|
|
22
|
+
parser.add_argument('command', nargs='?', help='Command to run')
|
|
23
|
+
parser.add_argument('args', nargs=argparse.REMAINDER, help='Arguments for the command')
|
|
24
|
+
|
|
25
|
+
args = parser.parse_args()
|
|
26
|
+
|
|
27
|
+
# Map common commands to aitrackdown equivalents
|
|
28
|
+
if args.command == 'create':
|
|
29
|
+
# Check if type is specified
|
|
30
|
+
if any(arg in ['-t', '--type'] for arg in args.args):
|
|
31
|
+
try:
|
|
32
|
+
type_idx = args.args.index('-t') if '-t' in args.args else args.args.index('--type')
|
|
33
|
+
if type_idx + 1 < len(args.args):
|
|
34
|
+
ticket_type = args.args[type_idx + 1]
|
|
35
|
+
# Remove type arguments
|
|
36
|
+
remaining_args = args.args[:type_idx] + args.args[type_idx + 2:]
|
|
37
|
+
|
|
38
|
+
if ticket_type == 'epic':
|
|
39
|
+
cmd = ['aitrackdown', 'epic', 'create'] + remaining_args
|
|
40
|
+
elif ticket_type == 'issue':
|
|
41
|
+
cmd = ['aitrackdown', 'issue', 'create'] + remaining_args
|
|
42
|
+
else:
|
|
43
|
+
cmd = ['aitrackdown', 'task', 'create'] + remaining_args
|
|
44
|
+
else:
|
|
45
|
+
cmd = ['aitrackdown', 'task', 'create'] + args.args
|
|
46
|
+
except:
|
|
47
|
+
cmd = ['aitrackdown', 'task', 'create'] + args.args
|
|
48
|
+
else:
|
|
49
|
+
cmd = ['aitrackdown', 'task', 'create'] + args.args
|
|
50
|
+
|
|
51
|
+
elif args.command == 'list':
|
|
52
|
+
cmd = ['aitrackdown', 'task', 'list'] + args.args
|
|
53
|
+
|
|
54
|
+
elif args.command in ['view', 'show']:
|
|
55
|
+
cmd = ['aitrackdown', 'task', 'show'] + args.args
|
|
56
|
+
|
|
57
|
+
elif args.command == 'update':
|
|
58
|
+
cmd = ['aitrackdown', 'task', 'update'] + args.args
|
|
59
|
+
|
|
60
|
+
elif args.command == 'close':
|
|
61
|
+
if args.args:
|
|
62
|
+
cmd = ['aitrackdown', 'task', 'complete', args.args[0]] + args.args[1:]
|
|
63
|
+
else:
|
|
64
|
+
cmd = ['aitrackdown', 'task', 'complete']
|
|
65
|
+
|
|
66
|
+
elif args.command in ['help', '--help', '-h', None]:
|
|
67
|
+
print("Claude MPM Ticket Management (powered by aitrackdown)")
|
|
68
|
+
print()
|
|
69
|
+
print("Usage:")
|
|
70
|
+
print(" claude-mpm-ticket create <title> [options]")
|
|
71
|
+
print(" claude-mpm-ticket list [options]")
|
|
72
|
+
print(" claude-mpm-ticket view <id>")
|
|
73
|
+
print(" claude-mpm-ticket update <id> [options]")
|
|
74
|
+
print(" claude-mpm-ticket close <id>")
|
|
75
|
+
print()
|
|
76
|
+
print("Examples:")
|
|
77
|
+
print(' claude-mpm-ticket create "Fix bug" -p high')
|
|
78
|
+
print(' claude-mpm-ticket create "New feature" -t issue')
|
|
79
|
+
print(' claude-mpm-ticket create "Roadmap" -t epic')
|
|
80
|
+
print(' claude-mpm-ticket list')
|
|
81
|
+
print(' claude-mpm-ticket view TSK-0001')
|
|
82
|
+
print()
|
|
83
|
+
print("For full options, use: aitrackdown --help")
|
|
84
|
+
return
|
|
85
|
+
|
|
86
|
+
else:
|
|
87
|
+
# Pass through to aitrackdown
|
|
88
|
+
cmd = ['aitrackdown'] + ([args.command] if args.command else []) + args.args
|
|
89
|
+
|
|
90
|
+
# Execute the command
|
|
91
|
+
try:
|
|
92
|
+
subprocess.run(cmd, check=True)
|
|
93
|
+
except subprocess.CalledProcessError as e:
|
|
94
|
+
sys.exit(e.returncode)
|
|
95
|
+
except FileNotFoundError:
|
|
96
|
+
print("Error: aitrackdown not found. Please ensure ai-trackdown-pytools is installed.")
|
|
97
|
+
print("Install with: pip install ai-trackdown-pytools")
|
|
98
|
+
sys.exit(1)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
if __name__ == "__main__":
|
|
102
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Configuration for hook service integration."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class HookConfig:
|
|
8
|
+
"""Hook service configuration."""
|
|
9
|
+
|
|
10
|
+
# Service settings
|
|
11
|
+
DEFAULT_PORT = 8080
|
|
12
|
+
PORT_RANGE_START = 8080
|
|
13
|
+
PORT_RANGE_END = 8090
|
|
14
|
+
|
|
15
|
+
# Timeouts
|
|
16
|
+
SERVICE_START_TIMEOUT = 3.0 # seconds
|
|
17
|
+
REQUEST_TIMEOUT = 30 # seconds
|
|
18
|
+
HEALTH_CHECK_TIMEOUT = 2.0 # seconds
|
|
19
|
+
|
|
20
|
+
# Paths
|
|
21
|
+
HOOK_SERVICE_LOG_DIR = Path.home() / ".claude-mpm" / "logs"
|
|
22
|
+
HOOK_SERVICE_PID_DIR = Path.home() / ".claude-mpm" / "run"
|
|
23
|
+
|
|
24
|
+
# Enable/disable hooks by default
|
|
25
|
+
HOOKS_ENABLED_BY_DEFAULT = True
|
|
26
|
+
|
|
27
|
+
# Hook service endpoints
|
|
28
|
+
HEALTH_ENDPOINT = "/health"
|
|
29
|
+
SUBMIT_HOOK_ENDPOINT = "/hooks/submit"
|
|
30
|
+
PRE_DELEGATION_HOOK_ENDPOINT = "/hooks/pre-delegation"
|
|
31
|
+
POST_DELEGATION_HOOK_ENDPOINT = "/hooks/post-delegation"
|
|
32
|
+
TICKET_EXTRACTION_HOOK_ENDPOINT = "/hooks/ticket-extraction"
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def get_hook_service_url(cls, port: int) -> str:
|
|
36
|
+
"""Get the hook service URL for a given port."""
|
|
37
|
+
return f"http://localhost:{port}"
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def is_hooks_enabled(cls) -> bool:
|
|
41
|
+
"""Check if hooks are enabled via environment variable."""
|
|
42
|
+
return os.environ.get("CLAUDE_MPM_HOOKS_ENABLED", str(cls.HOOKS_ENABLED_BY_DEFAULT)).lower() in ("true", "1", "yes")
|
claude_mpm/constants.py
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Constants for Claude MPM."""
|
|
2
|
+
|
|
3
|
+
from enum import Enum
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CLIPrefix(str, Enum):
|
|
7
|
+
"""CLI command prefix constants."""
|
|
8
|
+
MPM = "--mpm:"
|
|
9
|
+
|
|
10
|
+
def __add__(self, other: str) -> str:
|
|
11
|
+
"""Allow prefix + command concatenation."""
|
|
12
|
+
return self.value + other
|
|
13
|
+
|
|
14
|
+
def wrap(self, flag: str) -> str:
|
|
15
|
+
"""Wrap a flag with the prefix."""
|
|
16
|
+
if flag.startswith("--"):
|
|
17
|
+
return f"--mpm:{flag[2:]}"
|
|
18
|
+
elif flag.startswith("-"):
|
|
19
|
+
return f"-mpm:{flag[1:]}"
|
|
20
|
+
return self.value + flag
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CLICommands(str, Enum):
|
|
24
|
+
"""CLI command constants."""
|
|
25
|
+
RUN = "run"
|
|
26
|
+
TICKETS = "tickets"
|
|
27
|
+
INFO = "info"
|
|
28
|
+
AGENTS = "agents"
|
|
29
|
+
UI = "ui"
|
|
30
|
+
|
|
31
|
+
def with_prefix(self, prefix: CLIPrefix = CLIPrefix.MPM) -> str:
|
|
32
|
+
"""Get command with prefix."""
|
|
33
|
+
return prefix + self.value
|
|
34
|
+
|
|
35
|
+
@classmethod
|
|
36
|
+
def get_mpm_commands(cls) -> list[str]:
|
|
37
|
+
"""Get list of MPM-specific commands with prefix."""
|
|
38
|
+
return [cmd.with_prefix() for cmd in cls]
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def is_mpm_command(cls, command: str) -> bool:
|
|
42
|
+
"""Check if a command is an MPM command."""
|
|
43
|
+
# Check both with and without prefix
|
|
44
|
+
if command.startswith(CLIPrefix.MPM.value):
|
|
45
|
+
base_command = command[len(CLIPrefix.MPM.value):]
|
|
46
|
+
return base_command in [cmd.value for cmd in cls]
|
|
47
|
+
return command in [cmd.value for cmd in cls]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class AgentCommands(str, Enum):
|
|
51
|
+
"""Agent subcommand constants."""
|
|
52
|
+
LIST = "list"
|
|
53
|
+
DEPLOY = "deploy"
|
|
54
|
+
FORCE_DEPLOY = "force-deploy"
|
|
55
|
+
CLEAN = "clean"
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class CLIFlags(str, Enum):
|
|
59
|
+
"""CLI flag constants (without prefix)."""
|
|
60
|
+
# Logging flags
|
|
61
|
+
DEBUG = "debug"
|
|
62
|
+
LOGGING = "logging"
|
|
63
|
+
LOG_DIR = "log-dir"
|
|
64
|
+
|
|
65
|
+
# Framework flags
|
|
66
|
+
FRAMEWORK_PATH = "framework-path"
|
|
67
|
+
AGENTS_DIR = "agents-dir"
|
|
68
|
+
|
|
69
|
+
# Hook flags
|
|
70
|
+
NO_HOOKS = "no-hooks"
|
|
71
|
+
|
|
72
|
+
# Ticket flags
|
|
73
|
+
NO_TICKETS = "no-tickets"
|
|
74
|
+
|
|
75
|
+
# Input/output flags
|
|
76
|
+
INPUT = "input"
|
|
77
|
+
NON_INTERACTIVE = "non-interactive"
|
|
78
|
+
|
|
79
|
+
# Orchestration flags
|
|
80
|
+
SUBPROCESS = "subprocess"
|
|
81
|
+
INTERACTIVE_SUBPROCESS = "interactive-subprocess"
|
|
82
|
+
TODO_HIJACK = "todo-hijack"
|
|
83
|
+
|
|
84
|
+
# Agent flags
|
|
85
|
+
NO_NATIVE_AGENTS = "no-native-agents"
|
|
86
|
+
|
|
87
|
+
def with_prefix(self, short: bool = False) -> str:
|
|
88
|
+
"""Get flag with MPM prefix."""
|
|
89
|
+
prefix = CLIPrefix.MPM.value
|
|
90
|
+
if short and self in [self.DEBUG, self.INPUT]:
|
|
91
|
+
# Short flags
|
|
92
|
+
return f"-mpm:{self.value[0]}"
|
|
93
|
+
return f"{prefix}{self.value}"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class LogLevel(str, Enum):
|
|
97
|
+
"""Logging level constants."""
|
|
98
|
+
OFF = "OFF"
|
|
99
|
+
INFO = "INFO"
|
|
100
|
+
DEBUG = "DEBUG"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class OrchestratorMode(str, Enum):
|
|
104
|
+
"""Orchestrator mode constants."""
|
|
105
|
+
SYSTEM_PROMPT = "system_prompt"
|
|
106
|
+
SUBPROCESS = "subprocess"
|
|
107
|
+
INTERACTIVE_SUBPROCESS = "interactive_subprocess"
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class EnvironmentVars(str, Enum):
|
|
111
|
+
"""Environment variable constants."""
|
|
112
|
+
CLAUDE_CONFIG_DIR = "CLAUDE_CONFIG_DIR"
|
|
113
|
+
CLAUDE_MAX_PARALLEL_SUBAGENTS = "CLAUDE_MAX_PARALLEL_SUBAGENTS"
|
|
114
|
+
CLAUDE_TIMEOUT = "CLAUDE_TIMEOUT"
|
|
115
|
+
CLAUDE_MPM_DEBUG = "CLAUDE_MPM_DEBUG"
|
|
116
|
+
|
|
117
|
+
# Default values
|
|
118
|
+
DEFAULT_MAX_AGENTS = "10"
|
|
119
|
+
DEFAULT_TIMEOUT = "600000" # 10 minutes in milliseconds
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class Paths(str, Enum):
|
|
123
|
+
"""Path constants."""
|
|
124
|
+
CLAUDE_AGENTS_DIR = ".claude/agents"
|
|
125
|
+
CLAUDE_CONFIG_DIR = ".claude"
|
|
126
|
+
MPM_LOG_DIR = ".claude-mpm/logs"
|
|
127
|
+
MPM_SESSION_DIR = ".claude-mpm/session"
|
|
128
|
+
MPM_PROMPTS_DIR = ".claude-mpm/prompts"
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class AgentMetadata(str, Enum):
|
|
132
|
+
"""Agent metadata field constants."""
|
|
133
|
+
NAME = "name"
|
|
134
|
+
DESCRIPTION = "description"
|
|
135
|
+
VERSION = "version"
|
|
136
|
+
AUTHOR = "author"
|
|
137
|
+
TAGS = "tags"
|
|
138
|
+
TOOLS = "tools"
|
|
139
|
+
PRIORITY = "priority"
|
|
140
|
+
TIMEOUT = "timeout"
|
|
141
|
+
MAX_TOKENS = "max_tokens"
|
|
142
|
+
TEMPERATURE = "temperature"
|
|
143
|
+
|
|
144
|
+
# Default values
|
|
145
|
+
DEFAULT_AUTHOR = "claude-mpm"
|
|
146
|
+
DEFAULT_VERSION = "1.0.0"
|
|
147
|
+
DEFAULT_PRIORITY = "medium"
|
|
148
|
+
DEFAULT_TIMEOUT = 600
|
|
149
|
+
DEFAULT_MAX_TOKENS = 8192
|
|
150
|
+
DEFAULT_TEMPERATURE = 0.5
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Core components for Claude MPM."""
|
|
2
|
+
|
|
3
|
+
from .simple_runner import SimpleClaudeRunner
|
|
4
|
+
from .mixins import LoggerMixin
|
|
5
|
+
|
|
6
|
+
# Import config components if needed
|
|
7
|
+
try:
|
|
8
|
+
from .config import Config
|
|
9
|
+
from .config_aliases import ConfigAliases
|
|
10
|
+
except ImportError:
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
# Import DI components
|
|
14
|
+
try:
|
|
15
|
+
from .container import DIContainer, ServiceLifetime, get_container
|
|
16
|
+
from .service_registry import ServiceRegistry, get_service_registry, initialize_services
|
|
17
|
+
from .injectable_service import InjectableService
|
|
18
|
+
from .factories import (
|
|
19
|
+
ServiceFactory, HookManagerFactory, OrchestratorFactoryWrapper,
|
|
20
|
+
AgentServiceFactory, SessionManagerFactory, ConfigurationFactory,
|
|
21
|
+
get_factory_registry
|
|
22
|
+
)
|
|
23
|
+
except ImportError:
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"SimpleClaudeRunner",
|
|
28
|
+
"LoggerMixin",
|
|
29
|
+
"Config",
|
|
30
|
+
"ConfigAliases",
|
|
31
|
+
"DIContainer",
|
|
32
|
+
"ServiceLifetime",
|
|
33
|
+
"get_container",
|
|
34
|
+
"ServiceRegistry",
|
|
35
|
+
"get_service_registry",
|
|
36
|
+
"initialize_services",
|
|
37
|
+
"InjectableService",
|
|
38
|
+
"ServiceFactory",
|
|
39
|
+
"HookManagerFactory",
|
|
40
|
+
"OrchestratorFactoryWrapper",
|
|
41
|
+
"AgentServiceFactory",
|
|
42
|
+
"SessionManagerFactory",
|
|
43
|
+
"ConfigurationFactory",
|
|
44
|
+
"get_factory_registry",
|
|
45
|
+
]
|