claude-mpm 1.0.0__py3-none-any.whl → 2.0.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.
- claude_mpm/_version.py +4 -2
- claude_mpm/agents/INSTRUCTIONS.md +117 -312
- claude_mpm/agents/__init__.py +2 -2
- claude_mpm/agents/agent-template.yaml +83 -0
- claude_mpm/agents/agent_loader.py +192 -310
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +10 -15
- claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +46 -0
- claude_mpm/agents/templates/{engineer_agent.json → backup/engineer_agent_20250726_234551.json} +1 -1
- claude_mpm/agents/templates/data_engineer.json +107 -0
- claude_mpm/agents/templates/documentation.json +106 -0
- claude_mpm/agents/templates/engineer.json +110 -0
- claude_mpm/agents/templates/ops.json +106 -0
- claude_mpm/agents/templates/qa.json +106 -0
- claude_mpm/agents/templates/research.json +107 -0
- claude_mpm/agents/templates/security.json +105 -0
- claude_mpm/agents/templates/version_control.json +103 -0
- claude_mpm/cli.py +41 -47
- claude_mpm/cli_enhancements.py +297 -0
- claude_mpm/core/factories.py +1 -46
- claude_mpm/core/service_registry.py +0 -8
- claude_mpm/core/simple_runner.py +43 -0
- claude_mpm/generators/__init__.py +5 -0
- claude_mpm/generators/agent_profile_generator.py +137 -0
- claude_mpm/hooks/README.md +75 -221
- claude_mpm/hooks/builtin/mpm_command_hook.py +125 -0
- claude_mpm/hooks/claude_hooks/__init__.py +5 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +399 -0
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +47 -0
- claude_mpm/hooks/validation_hooks.py +181 -0
- claude_mpm/schemas/agent_schema.json +328 -0
- claude_mpm/services/agent_management_service.py +4 -4
- claude_mpm/services/agent_profile_loader.py +1 -1
- claude_mpm/services/agent_registry.py +0 -1
- claude_mpm/services/base_agent_manager.py +3 -3
- claude_mpm/utils/error_handler.py +247 -0
- claude_mpm/validation/__init__.py +5 -0
- claude_mpm/validation/agent_validator.py +302 -0
- {claude_mpm-1.0.0.dist-info → claude_mpm-2.0.0.dist-info}/METADATA +133 -22
- {claude_mpm-1.0.0.dist-info → claude_mpm-2.0.0.dist-info}/RECORD +49 -37
- claude_mpm/agents/templates/data_engineer_agent.json +0 -46
- claude_mpm/agents/templates/update-optimized-specialized-agents.json +0 -374
- claude_mpm/config/hook_config.py +0 -42
- claude_mpm/hooks/hook_client.py +0 -264
- claude_mpm/hooks/hook_runner.py +0 -370
- claude_mpm/hooks/json_rpc_executor.py +0 -259
- claude_mpm/hooks/json_rpc_hook_client.py +0 -319
- claude_mpm/services/hook_service.py +0 -388
- claude_mpm/services/hook_service_manager.py +0 -223
- claude_mpm/services/json_rpc_hook_manager.py +0 -92
- /claude_mpm/agents/templates/{documentation_agent.json → backup/documentation_agent_20250726_234551.json} +0 -0
- /claude_mpm/agents/templates/{ops_agent.json → backup/ops_agent_20250726_234551.json} +0 -0
- /claude_mpm/agents/templates/{qa_agent.json → backup/qa_agent_20250726_234551.json} +0 -0
- /claude_mpm/agents/templates/{research_agent.json → backup/research_agent_20250726_234551.json} +0 -0
- /claude_mpm/agents/templates/{security_agent.json → backup/security_agent_20250726_234551.json} +0 -0
- /claude_mpm/agents/templates/{version_control_agent.json → backup/version_control_agent_20250726_234551.json} +0 -0
- {claude_mpm-1.0.0.dist-info → claude_mpm-2.0.0.dist-info}/WHEEL +0 -0
- {claude_mpm-1.0.0.dist-info → claude_mpm-2.0.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-1.0.0.dist-info → claude_mpm-2.0.0.dist-info}/top_level.txt +0 -0
claude_mpm/hooks/README.md
CHANGED
|
@@ -1,243 +1,97 @@
|
|
|
1
|
-
# Claude
|
|
1
|
+
# Claude Code Hooks System
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Current Implementation (v0.5.0+)
|
|
6
|
-
|
|
7
|
-
As of version 0.5.0, the hook system uses JSON-RPC for all hook executions. The previous HTTP-based implementation is deprecated and will be removed in a future release.
|
|
3
|
+
This directory contains the Claude Code hook integration for claude-mpm.
|
|
8
4
|
|
|
9
5
|
## Overview
|
|
10
6
|
|
|
11
|
-
The hook system allows
|
|
12
|
-
|
|
13
|
-
- **Submit Hooks**: Process user prompts before orchestration
|
|
14
|
-
- **Pre-Delegation Hooks**: Filter/enhance context before delegating to agents
|
|
15
|
-
- **Post-Delegation Hooks**: Validate/process results from agents
|
|
16
|
-
- **Ticket Extraction Hooks**: Automatically extract and create tickets from conversations
|
|
7
|
+
The hook system allows claude-mpm to intercept and handle commands typed in Claude Code, particularly the `/mpm` commands.
|
|
17
8
|
|
|
18
|
-
##
|
|
9
|
+
## Structure
|
|
19
10
|
|
|
20
11
|
```
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
│
|
|
24
|
-
│
|
|
25
|
-
|
|
26
|
-
│ - Create tickets│ │ - Auto discovery │ │ - PostDelegation│
|
|
27
|
-
└─────────────────┘ └──────────────────┘ │ - TicketExtract │
|
|
28
|
-
└─────────────────┘
|
|
12
|
+
hooks/
|
|
13
|
+
├── claude_hooks/ # Claude Code hook implementation
|
|
14
|
+
│ ├── hook_handler.py # Main Python handler that processes events
|
|
15
|
+
│ └── hook_wrapper.sh # Shell wrapper script (this is what gets installed in ~/.claude/settings.json)
|
|
16
|
+
└── builtin/ # Legacy internal hooks (deprecated)
|
|
29
17
|
```
|
|
30
18
|
|
|
31
|
-
##
|
|
19
|
+
## Claude Code Hooks
|
|
32
20
|
|
|
33
|
-
|
|
34
|
-
```python
|
|
35
|
-
from claude_mpm.hooks.json_rpc_hook_client import JSONRPCHookClient
|
|
21
|
+
The Claude Code hooks are the primary integration point between claude-mpm and Claude Code. They allow:
|
|
36
22
|
|
|
37
|
-
|
|
38
|
-
|
|
23
|
+
- Intercepting `/mpm` commands before they reach the LLM
|
|
24
|
+
- Providing custom responses and actions
|
|
25
|
+
- Blocking LLM processing when appropriate
|
|
39
26
|
|
|
40
|
-
|
|
41
|
-
health = client.health_check()
|
|
42
|
-
print(f"Status: {health['status']}")
|
|
43
|
-
print(f"Hooks available: {health['hook_count']}")
|
|
27
|
+
### Installation
|
|
44
28
|
|
|
45
|
-
|
|
46
|
-
hooks = client.list_hooks()
|
|
47
|
-
for hook_type, hook_list in hooks.items():
|
|
48
|
-
print(f"{hook_type}: {len(hook_list)} hooks")
|
|
49
|
-
```
|
|
29
|
+
To install the Claude Code hooks:
|
|
50
30
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
# Execute submit hooks
|
|
54
|
-
results = client.execute_submit_hook(
|
|
55
|
-
prompt="URGENT: Fix the login bug",
|
|
56
|
-
user_id="user123"
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
# Get modified data
|
|
60
|
-
modified_data = client.get_modified_data(results)
|
|
61
|
-
if modified_data.get('priority') == 'high':
|
|
62
|
-
print("High priority task detected!")
|
|
63
|
-
|
|
64
|
-
# Execute pre-delegation hooks
|
|
65
|
-
results = client.execute_pre_delegation_hook(
|
|
66
|
-
agent="engineer",
|
|
67
|
-
context={"task": "implement feature"}
|
|
68
|
-
)
|
|
69
|
-
|
|
70
|
-
# Execute ticket extraction
|
|
71
|
-
results = client.execute_ticket_extraction_hook(
|
|
72
|
-
content="TODO: Add tests\nFIXME: Memory leak"
|
|
73
|
-
)
|
|
74
|
-
tickets = client.get_extracted_tickets(results)
|
|
31
|
+
```bash
|
|
32
|
+
python scripts/install_hooks.py
|
|
75
33
|
```
|
|
76
34
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```python
|
|
82
|
-
from claude_mpm.hooks.base_hook import SubmitHook, HookContext, HookResult
|
|
83
|
-
|
|
84
|
-
class TicketDetectionSubmitHook(SubmitHook):
|
|
85
|
-
name = "ticket_detection"
|
|
86
|
-
priority = 10
|
|
87
|
-
|
|
88
|
-
def execute(self, context: HookContext) -> HookResult:
|
|
89
|
-
prompt = context.data.get('prompt', '')
|
|
90
|
-
# Detect ticket references like TSK-001
|
|
91
|
-
tickets = self.ticket_pattern.findall(prompt)
|
|
92
|
-
return HookResult(
|
|
93
|
-
success=True,
|
|
94
|
-
data={'tickets': tickets},
|
|
95
|
-
modified=True
|
|
96
|
-
)
|
|
97
|
-
```
|
|
35
|
+
This will:
|
|
36
|
+
1. Create/update `~/.claude/settings.json` with hook configuration
|
|
37
|
+
2. Point to the `hook_wrapper.sh` script
|
|
38
|
+
3. Copy any custom commands to `~/.claude/commands/`
|
|
98
39
|
|
|
99
|
-
###
|
|
100
|
-
Modify agent context before delegation:
|
|
101
|
-
```python
|
|
102
|
-
from claude_mpm.hooks.base_hook import PreDelegationHook
|
|
103
|
-
|
|
104
|
-
class ContextFilterHook(PreDelegationHook):
|
|
105
|
-
name = "context_filter"
|
|
106
|
-
priority = 20
|
|
107
|
-
|
|
108
|
-
def execute(self, context: HookContext) -> HookResult:
|
|
109
|
-
# Filter sensitive information
|
|
110
|
-
filtered_context = self._filter_sensitive(context.data['context'])
|
|
111
|
-
return HookResult(
|
|
112
|
-
success=True,
|
|
113
|
-
data={'context': filtered_context},
|
|
114
|
-
modified=True
|
|
115
|
-
)
|
|
116
|
-
```
|
|
40
|
+
### How It Works
|
|
117
41
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
from
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
success=True,
|
|
133
|
-
data={'validation_issues': issues},
|
|
134
|
-
modified=bool(issues)
|
|
135
|
-
)
|
|
136
|
-
```
|
|
42
|
+
1. When you type in Claude Code, it triggers hook events
|
|
43
|
+
2. Claude Code calls `hook_wrapper.sh` (the path in `~/.claude/settings.json`)
|
|
44
|
+
3. The wrapper script:
|
|
45
|
+
- Detects if it's running from a local dev environment, npm, or PyPI installation
|
|
46
|
+
- Activates the appropriate Python environment
|
|
47
|
+
- Runs `hook_handler.py` with the event data
|
|
48
|
+
4. The handler processes various event types:
|
|
49
|
+
- **UserPromptSubmit**: Checks if the prompt starts with `/mpm` and handles commands
|
|
50
|
+
- **PreToolUse**: Logs tool usage before execution
|
|
51
|
+
- **PostToolUse**: Logs tool results after execution
|
|
52
|
+
- **Stop**: Logs when a session or task stops
|
|
53
|
+
- **SubagentStop**: Logs when a subagent completes with agent type and ID
|
|
54
|
+
5. For `/mpm` commands, it returns exit code 2 to block LLM processing
|
|
55
|
+
6. All events are logged to project-specific log files in `.claude-mpm/logs/`
|
|
137
56
|
|
|
138
|
-
###
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def execute(self, context: HookContext) -> HookResult:
|
|
148
|
-
content = context.data.get('content', '')
|
|
149
|
-
# Extract TODO, FIXME, etc.
|
|
150
|
-
tickets = self._extract_tickets(content)
|
|
151
|
-
return HookResult(
|
|
152
|
-
success=True,
|
|
153
|
-
data={'tickets': tickets},
|
|
154
|
-
modified=True
|
|
155
|
-
)
|
|
156
|
-
```
|
|
57
|
+
### Available Commands
|
|
58
|
+
|
|
59
|
+
- `/mpm` - Show help and available commands
|
|
60
|
+
- `/mpm status` - Show claude-mpm status and environment
|
|
61
|
+
- `/mpm help` - Show detailed help
|
|
62
|
+
|
|
63
|
+
### Debugging
|
|
64
|
+
|
|
65
|
+
To enable debug logging for hooks:
|
|
157
66
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
### 1. Create Hook File
|
|
161
|
-
Create a new Python file in the `builtin/` directory:
|
|
162
|
-
|
|
163
|
-
```python
|
|
164
|
-
# builtin/my_custom_hook.py
|
|
165
|
-
from claude_mpm.hooks.base_hook import SubmitHook, HookContext, HookResult
|
|
166
|
-
|
|
167
|
-
class MyCustomHook(SubmitHook):
|
|
168
|
-
name = "my_custom_hook"
|
|
169
|
-
priority = 25 # 0-100, lower executes first
|
|
170
|
-
|
|
171
|
-
def execute(self, context: HookContext) -> HookResult:
|
|
172
|
-
# Your hook logic here
|
|
173
|
-
prompt = context.data.get('prompt', '')
|
|
174
|
-
|
|
175
|
-
# Process prompt
|
|
176
|
-
processed = self._process(prompt)
|
|
177
|
-
|
|
178
|
-
return HookResult(
|
|
179
|
-
success=True,
|
|
180
|
-
data={'prompt': processed},
|
|
181
|
-
modified=True
|
|
182
|
-
)
|
|
183
|
-
|
|
184
|
-
def _process(self, prompt: str) -> str:
|
|
185
|
-
# Your processing logic
|
|
186
|
-
return prompt.upper()
|
|
67
|
+
```bash
|
|
68
|
+
export CLAUDE_MPM_LOG_LEVEL=DEBUG
|
|
187
69
|
```
|
|
188
70
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
-
|
|
208
|
-
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
5. **Log Important Events**: Use logging for debugging and monitoring
|
|
217
|
-
6. **Make Hooks Idempotent**: Hooks should produce same result if run multiple times
|
|
218
|
-
|
|
219
|
-
## Troubleshooting
|
|
220
|
-
|
|
221
|
-
### Hooks Not Discovered
|
|
222
|
-
- Verify hook file is in `builtin/` directory
|
|
223
|
-
- Check file has `.py` extension
|
|
224
|
-
- Ensure hook class inherits from correct base type
|
|
225
|
-
- Check for Python syntax errors
|
|
226
|
-
|
|
227
|
-
### Hook Execution Errors
|
|
228
|
-
- Enable debug logging to see detailed errors
|
|
229
|
-
- Check hook's execute method returns HookResult
|
|
230
|
-
- Verify context data structure matches expectations
|
|
231
|
-
|
|
232
|
-
### Performance Issues
|
|
233
|
-
- Check hook execution times in results
|
|
234
|
-
- Consider caching expensive operations
|
|
235
|
-
- Profile hooks with `cProfile` if needed
|
|
236
|
-
|
|
237
|
-
## Examples
|
|
238
|
-
|
|
239
|
-
See the `builtin/` directory for example implementations:
|
|
240
|
-
- `submit_hook_example.py`: Ticket and priority detection
|
|
241
|
-
- `pre_delegation_hook_example.py`: Context filtering and enhancement
|
|
242
|
-
- `post_delegation_hook_example.py`: Result validation and metrics
|
|
243
|
-
- `ticket_extraction_hook_example.py`: Automatic ticket extraction
|
|
71
|
+
Then run Claude Code from that terminal. Hook events will be logged to `~/.claude-mpm/logs/`.
|
|
72
|
+
|
|
73
|
+
## Legacy Hook System (Deprecated)
|
|
74
|
+
|
|
75
|
+
The `builtin/` directory contains the old internal hook system that was designed for JSON-RPC based hooks. This system is deprecated and will be removed in a future version. All hook functionality is now handled through the Claude Code hooks.
|
|
76
|
+
|
|
77
|
+
## Development
|
|
78
|
+
|
|
79
|
+
To add new `/mpm` commands:
|
|
80
|
+
|
|
81
|
+
1. Edit `hook_handler.py` to handle the new command
|
|
82
|
+
2. Update the help text in the `handle_mpm_help()` function
|
|
83
|
+
3. Test by running Claude Code with the new command
|
|
84
|
+
|
|
85
|
+
## Exit Codes
|
|
86
|
+
|
|
87
|
+
The hook system uses specific exit codes:
|
|
88
|
+
|
|
89
|
+
- `0` - Success, continue normal processing
|
|
90
|
+
- `2` - Block LLM processing (command was handled)
|
|
91
|
+
- Other - Error occurred
|
|
92
|
+
|
|
93
|
+
## Environment Variables
|
|
94
|
+
|
|
95
|
+
- `CLAUDE_MPM_LOG_LEVEL` - Set to DEBUG for detailed logging
|
|
96
|
+
- `HOOK_EVENT_TYPE` - Set by Claude Code (UserPromptSubmit, PreToolUse, PostToolUse)
|
|
97
|
+
- `HOOK_DATA` - JSON data from Claude Code with event details
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""Hook to intercept and handle /mpm: commands."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from claude_mpm.hooks.base_hook import SubmitHook, HookContext, HookResult
|
|
9
|
+
from claude_mpm.core.logger import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MpmCommandHook(SubmitHook):
|
|
15
|
+
"""Hook that intercepts /mpm: commands and routes them to the command router."""
|
|
16
|
+
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__(name="mpm_command", priority=1) # High priority to intercept early
|
|
19
|
+
self.command_prefix = "/mpm:"
|
|
20
|
+
self.command_router_path = self._find_command_router()
|
|
21
|
+
|
|
22
|
+
def _find_command_router(self) -> Path:
|
|
23
|
+
"""Find the command router script."""
|
|
24
|
+
# Look for command router relative to project root
|
|
25
|
+
possible_paths = [
|
|
26
|
+
Path(".claude/scripts/command_router.py"),
|
|
27
|
+
Path(__file__).parent.parent.parent.parent.parent / ".claude/scripts/command_router.py"
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
for path in possible_paths:
|
|
31
|
+
if path.exists():
|
|
32
|
+
return path.resolve()
|
|
33
|
+
|
|
34
|
+
# Default path
|
|
35
|
+
return Path(".claude/scripts/command_router.py").resolve()
|
|
36
|
+
|
|
37
|
+
def execute(self, context: HookContext) -> HookResult:
|
|
38
|
+
"""Check for /mpm: commands and execute them directly."""
|
|
39
|
+
try:
|
|
40
|
+
prompt = context.data.get('prompt', '').strip()
|
|
41
|
+
|
|
42
|
+
# Check if this is an /mpm: command
|
|
43
|
+
if not prompt.startswith(self.command_prefix):
|
|
44
|
+
# Not our command, pass through
|
|
45
|
+
return HookResult(
|
|
46
|
+
success=True,
|
|
47
|
+
data=context.data,
|
|
48
|
+
modified=False
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Extract command and arguments
|
|
52
|
+
command_line = prompt[len(self.command_prefix):].strip()
|
|
53
|
+
parts = command_line.split()
|
|
54
|
+
|
|
55
|
+
if not parts:
|
|
56
|
+
return HookResult(
|
|
57
|
+
success=True,
|
|
58
|
+
data={
|
|
59
|
+
'prompt': '',
|
|
60
|
+
'response': "No command specified. Available commands: test",
|
|
61
|
+
'skip_llm': True
|
|
62
|
+
},
|
|
63
|
+
modified=True,
|
|
64
|
+
metadata={'command_handled': True}
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
command = parts[0]
|
|
68
|
+
args = parts[1:]
|
|
69
|
+
|
|
70
|
+
logger.info(f"Executing /mpm:{command} with args: {args}")
|
|
71
|
+
|
|
72
|
+
# Execute command using command router
|
|
73
|
+
try:
|
|
74
|
+
# Run the command router script
|
|
75
|
+
cmd = [sys.executable, str(self.command_router_path), command] + args
|
|
76
|
+
result = subprocess.run(
|
|
77
|
+
cmd,
|
|
78
|
+
capture_output=True,
|
|
79
|
+
text=True,
|
|
80
|
+
check=False
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if result.returncode == 0:
|
|
84
|
+
response = result.stdout.strip()
|
|
85
|
+
else:
|
|
86
|
+
response = f"Command failed: {result.stderr.strip() or 'Unknown error'}"
|
|
87
|
+
|
|
88
|
+
logger.info(f"Command result: {response}")
|
|
89
|
+
|
|
90
|
+
# Return result without going to LLM
|
|
91
|
+
return HookResult(
|
|
92
|
+
success=True,
|
|
93
|
+
data={
|
|
94
|
+
'prompt': '', # Clear prompt to prevent LLM processing
|
|
95
|
+
'response': response,
|
|
96
|
+
'skip_llm': True # Flag to skip LLM
|
|
97
|
+
},
|
|
98
|
+
modified=True,
|
|
99
|
+
metadata={
|
|
100
|
+
'command_handled': True,
|
|
101
|
+
'command': command,
|
|
102
|
+
'args': args
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
except Exception as e:
|
|
107
|
+
logger.error(f"Failed to execute command: {e}")
|
|
108
|
+
return HookResult(
|
|
109
|
+
success=True,
|
|
110
|
+
data={
|
|
111
|
+
'prompt': '',
|
|
112
|
+
'response': f"Error executing command: {str(e)}",
|
|
113
|
+
'skip_llm': True
|
|
114
|
+
},
|
|
115
|
+
modified=True,
|
|
116
|
+
metadata={'command_error': str(e)}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
except Exception as e:
|
|
120
|
+
logger.error(f"MPM command hook failed: {e}")
|
|
121
|
+
# On error, pass through to normal processing
|
|
122
|
+
return HookResult(
|
|
123
|
+
success=False,
|
|
124
|
+
error=str(e)
|
|
125
|
+
)
|