claude-mpm 4.14.6__py3-none-any.whl → 4.14.8__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/VERSION +1 -1
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/cli/__init__.py +34 -740
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +204 -148
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +159 -1801
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +165 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +35 -21
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +455 -0
- claude_mpm/core/enums.py +322 -0
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +6 -3
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +3 -2
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/diagnostics/checks/installation_check.py +3 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +20 -6
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +8 -7
- claude_mpm/services/memory_hook_service.py +4 -1
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/socketio/handlers/hook.py +3 -2
- claude_mpm/services/socketio/server/main.py +3 -1
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +5 -4
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +5 -4
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +4 -3
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +4 -3
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +3 -2
- claude_mpm/services/unified/deployment_strategies/utils.py +2 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +2 -1
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +7 -6
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +7 -2
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/METADATA +1 -1
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/RECORD +74 -64
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/WHEEL +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.14.6.dist-info → claude_mpm-4.14.8.dist-info}/top_level.txt +0 -0
claude_mpm/core/enums.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized enums for type-safe string constants across Claude MPM.
|
|
3
|
+
|
|
4
|
+
This module provides enumerated types to replace magic strings throughout the codebase,
|
|
5
|
+
improving type safety, IDE autocomplete, and preventing typos.
|
|
6
|
+
|
|
7
|
+
Created: 2025-10-25
|
|
8
|
+
Priority: Phase 1 of systematic enum migration (3-4 week plan)
|
|
9
|
+
Impact: Replaces 2,050+ magic string occurrences
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from claude_mpm.core.enums import OperationResult, OutputFormat, ServiceState
|
|
13
|
+
|
|
14
|
+
# Type-safe operation results
|
|
15
|
+
result = OperationResult.SUCCESS
|
|
16
|
+
if result == OperationResult.SUCCESS:
|
|
17
|
+
print("Operation completed successfully")
|
|
18
|
+
|
|
19
|
+
# Type-safe output formatting
|
|
20
|
+
format_type = OutputFormat.JSON
|
|
21
|
+
|
|
22
|
+
# Type-safe service state management
|
|
23
|
+
state = ServiceState.RUNNING
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from enum import StrEnum
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class OperationResult(StrEnum):
|
|
30
|
+
"""
|
|
31
|
+
Standard result codes for operations throughout Claude MPM.
|
|
32
|
+
|
|
33
|
+
Replaces 876+ occurrences of magic strings like "success", "error", "failed".
|
|
34
|
+
Used in: CLI commands, service operations, API responses, hook handlers.
|
|
35
|
+
|
|
36
|
+
Migration Priority: HIGH (Week 1)
|
|
37
|
+
Coverage: ~42% of all magic strings
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
SUCCESS = "success"
|
|
41
|
+
"""Operation completed successfully."""
|
|
42
|
+
|
|
43
|
+
ERROR = "error"
|
|
44
|
+
"""Operation encountered an error."""
|
|
45
|
+
|
|
46
|
+
FAILED = "failed"
|
|
47
|
+
"""Operation failed to complete."""
|
|
48
|
+
|
|
49
|
+
PENDING = "pending"
|
|
50
|
+
"""Operation is waiting to execute."""
|
|
51
|
+
|
|
52
|
+
COMPLETED = "completed"
|
|
53
|
+
"""Operation has been completed."""
|
|
54
|
+
|
|
55
|
+
TIMEOUT = "timeout"
|
|
56
|
+
"""Operation exceeded time limit."""
|
|
57
|
+
|
|
58
|
+
CANCELLED = "cancelled"
|
|
59
|
+
"""Operation was cancelled before completion."""
|
|
60
|
+
|
|
61
|
+
CONTEXT_READY = "context_ready"
|
|
62
|
+
"""Context is prepared and ready for use."""
|
|
63
|
+
|
|
64
|
+
SKIPPED = "skipped"
|
|
65
|
+
"""Operation was intentionally skipped."""
|
|
66
|
+
|
|
67
|
+
RETRY = "retry"
|
|
68
|
+
"""Operation should be retried."""
|
|
69
|
+
|
|
70
|
+
PARTIAL = "partial"
|
|
71
|
+
"""Operation completed partially."""
|
|
72
|
+
|
|
73
|
+
UNKNOWN = "unknown"
|
|
74
|
+
"""Operation result is unknown or indeterminate."""
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class OutputFormat(StrEnum):
|
|
78
|
+
"""
|
|
79
|
+
Output format options for CLI commands and logging.
|
|
80
|
+
|
|
81
|
+
Replaces 200+ occurrences of format strings.
|
|
82
|
+
Used in: CLI output, logging, configuration exports, API responses.
|
|
83
|
+
|
|
84
|
+
Migration Priority: HIGH (Week 1)
|
|
85
|
+
Coverage: ~10% of all magic strings
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
JSON = "json"
|
|
89
|
+
"""JavaScript Object Notation format."""
|
|
90
|
+
|
|
91
|
+
YAML = "yaml"
|
|
92
|
+
"""YAML Ain't Markup Language format."""
|
|
93
|
+
|
|
94
|
+
TEXT = "text"
|
|
95
|
+
"""Plain text format."""
|
|
96
|
+
|
|
97
|
+
MARKDOWN = "markdown"
|
|
98
|
+
"""Markdown formatted text."""
|
|
99
|
+
|
|
100
|
+
RAW = "raw"
|
|
101
|
+
"""Raw unformatted output."""
|
|
102
|
+
|
|
103
|
+
TABLE = "table"
|
|
104
|
+
"""Tabular format for display."""
|
|
105
|
+
|
|
106
|
+
CSV = "csv"
|
|
107
|
+
"""Comma-separated values format."""
|
|
108
|
+
|
|
109
|
+
HTML = "html"
|
|
110
|
+
"""HyperText Markup Language format."""
|
|
111
|
+
|
|
112
|
+
XML = "xml"
|
|
113
|
+
"""eXtensible Markup Language format."""
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class ServiceState(StrEnum):
|
|
117
|
+
"""
|
|
118
|
+
Service lifecycle states for all Claude MPM services.
|
|
119
|
+
|
|
120
|
+
Replaces 150+ occurrences of service state strings.
|
|
121
|
+
Used in: Hook services, MCP servers, monitoring, health checks.
|
|
122
|
+
|
|
123
|
+
Migration Priority: HIGH (Week 1)
|
|
124
|
+
Coverage: ~7% of all magic strings
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
STOPPED = "stopped"
|
|
128
|
+
"""Service is completely stopped."""
|
|
129
|
+
|
|
130
|
+
STARTING = "starting"
|
|
131
|
+
"""Service is in the process of starting."""
|
|
132
|
+
|
|
133
|
+
RUNNING = "running"
|
|
134
|
+
"""Service is actively running."""
|
|
135
|
+
|
|
136
|
+
STOPPING = "stopping"
|
|
137
|
+
"""Service is in the process of stopping."""
|
|
138
|
+
|
|
139
|
+
RESTARTING = "restarting"
|
|
140
|
+
"""Service is restarting."""
|
|
141
|
+
|
|
142
|
+
ERROR = "error"
|
|
143
|
+
"""Service encountered an error."""
|
|
144
|
+
|
|
145
|
+
UNKNOWN = "unknown"
|
|
146
|
+
"""Service state cannot be determined."""
|
|
147
|
+
|
|
148
|
+
DEGRADED = "degraded"
|
|
149
|
+
"""Service is running but with reduced functionality."""
|
|
150
|
+
|
|
151
|
+
IDLE = "idle"
|
|
152
|
+
"""Service is running but not actively processing."""
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class ValidationSeverity(StrEnum):
|
|
156
|
+
"""
|
|
157
|
+
Severity levels for validation and error reporting.
|
|
158
|
+
|
|
159
|
+
Replaces validation severity strings across validators and error handlers.
|
|
160
|
+
Used in: Frontmatter validation, API validation, config validation.
|
|
161
|
+
|
|
162
|
+
Migration Priority: MEDIUM (Week 2)
|
|
163
|
+
Coverage: ~5% of all magic strings
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
INFO = "info"
|
|
167
|
+
"""Informational message, no action required."""
|
|
168
|
+
|
|
169
|
+
WARNING = "warning"
|
|
170
|
+
"""Warning that should be addressed but not critical."""
|
|
171
|
+
|
|
172
|
+
ERROR = "error"
|
|
173
|
+
"""Error that prevents operation completion."""
|
|
174
|
+
|
|
175
|
+
CRITICAL = "critical"
|
|
176
|
+
"""Critical error requiring immediate attention."""
|
|
177
|
+
|
|
178
|
+
DEBUG = "debug"
|
|
179
|
+
"""Debug-level information for troubleshooting."""
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class ModelTier(StrEnum):
|
|
183
|
+
"""
|
|
184
|
+
Claude model tier classifications and identifiers.
|
|
185
|
+
|
|
186
|
+
Replaces model name strings and enables model normalization.
|
|
187
|
+
Used in: Agent configuration, API calls, capability detection.
|
|
188
|
+
|
|
189
|
+
Migration Priority: MEDIUM (Week 2)
|
|
190
|
+
Coverage: ~4% of all magic strings
|
|
191
|
+
|
|
192
|
+
Notes:
|
|
193
|
+
- Replaces manual model normalization code
|
|
194
|
+
- Enables type-safe model selection
|
|
195
|
+
- Provides both tier names and full model identifiers
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
# Tier names (simplified)
|
|
199
|
+
OPUS = "opus"
|
|
200
|
+
"""Claude Opus tier (highest capability)."""
|
|
201
|
+
|
|
202
|
+
SONNET = "sonnet"
|
|
203
|
+
"""Claude Sonnet tier (balanced)."""
|
|
204
|
+
|
|
205
|
+
HAIKU = "haiku"
|
|
206
|
+
"""Claude Haiku tier (fastest)."""
|
|
207
|
+
|
|
208
|
+
# Full model identifiers (Claude 4.x)
|
|
209
|
+
OPUS_4 = "claude-opus-4-20250514"
|
|
210
|
+
"""Claude 4 Opus - May 2025 release."""
|
|
211
|
+
|
|
212
|
+
SONNET_4 = "claude-sonnet-4-20250514"
|
|
213
|
+
"""Claude 4 Sonnet - May 2025 release."""
|
|
214
|
+
|
|
215
|
+
SONNET_4_5 = "claude-sonnet-4-5-20250929"
|
|
216
|
+
"""Claude 4.5 Sonnet - September 2025 release."""
|
|
217
|
+
|
|
218
|
+
# Legacy model identifiers (Claude 3.x)
|
|
219
|
+
OPUS_3 = "claude-3-opus-20240229"
|
|
220
|
+
"""Claude 3 Opus - February 2024 release."""
|
|
221
|
+
|
|
222
|
+
SONNET_3_5 = "claude-3-5-sonnet-20241022"
|
|
223
|
+
"""Claude 3.5 Sonnet - October 2024 release."""
|
|
224
|
+
|
|
225
|
+
HAIKU_3 = "claude-3-haiku-20240307"
|
|
226
|
+
"""Claude 3 Haiku - March 2024 release."""
|
|
227
|
+
|
|
228
|
+
@classmethod
|
|
229
|
+
def normalize(cls, model_name: str) -> "ModelTier":
|
|
230
|
+
"""
|
|
231
|
+
Normalize a model name to its canonical tier.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
model_name: Any model name variant (e.g., "opus", "claude-opus-4", "OPUS")
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
Normalized ModelTier enum value
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
>>> ModelTier.normalize("OPUS")
|
|
241
|
+
ModelTier.OPUS
|
|
242
|
+
>>> ModelTier.normalize("claude-sonnet-4-20250514")
|
|
243
|
+
ModelTier.SONNET_4
|
|
244
|
+
>>> ModelTier.normalize("sonnet")
|
|
245
|
+
ModelTier.SONNET
|
|
246
|
+
"""
|
|
247
|
+
normalized = model_name.lower().strip()
|
|
248
|
+
|
|
249
|
+
# Direct enum value match
|
|
250
|
+
for tier in cls:
|
|
251
|
+
if tier.value == normalized:
|
|
252
|
+
return tier
|
|
253
|
+
|
|
254
|
+
# Tier name extraction
|
|
255
|
+
if "opus" in normalized:
|
|
256
|
+
return cls.OPUS
|
|
257
|
+
if "sonnet" in normalized:
|
|
258
|
+
return cls.SONNET
|
|
259
|
+
if "haiku" in normalized:
|
|
260
|
+
return cls.HAIKU
|
|
261
|
+
|
|
262
|
+
# Default to sonnet for unknown models
|
|
263
|
+
return cls.SONNET
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class AgentCategory(StrEnum):
|
|
267
|
+
"""
|
|
268
|
+
Agent specialization categories for classification and routing.
|
|
269
|
+
|
|
270
|
+
Replaces category strings in agent configurations and routing logic.
|
|
271
|
+
Used in: Agent templates, capability detection, routing decisions.
|
|
272
|
+
|
|
273
|
+
Migration Priority: MEDIUM (Week 3)
|
|
274
|
+
Coverage: ~3% of all magic strings
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
RESEARCH = "research"
|
|
278
|
+
"""Research and analysis agents."""
|
|
279
|
+
|
|
280
|
+
ENGINEERING = "engineering"
|
|
281
|
+
"""Software engineering and implementation agents."""
|
|
282
|
+
|
|
283
|
+
QA = "qa"
|
|
284
|
+
"""Quality assurance and testing agents."""
|
|
285
|
+
|
|
286
|
+
SECURITY = "security"
|
|
287
|
+
"""Security analysis and vulnerability assessment agents."""
|
|
288
|
+
|
|
289
|
+
DOCUMENTATION = "documentation"
|
|
290
|
+
"""Documentation and technical writing agents."""
|
|
291
|
+
|
|
292
|
+
OPERATIONS = "operations"
|
|
293
|
+
"""DevOps and infrastructure management agents."""
|
|
294
|
+
|
|
295
|
+
DATA = "data"
|
|
296
|
+
"""Data engineering and analytics agents."""
|
|
297
|
+
|
|
298
|
+
VERSION_CONTROL = "version_control"
|
|
299
|
+
"""Version control and release management agents."""
|
|
300
|
+
|
|
301
|
+
GENERAL = "general"
|
|
302
|
+
"""General-purpose agents without specific specialization."""
|
|
303
|
+
|
|
304
|
+
CUSTOM = "custom"
|
|
305
|
+
"""User-defined custom agent categories."""
|
|
306
|
+
|
|
307
|
+
PROJECT_MANAGEMENT = "project_management"
|
|
308
|
+
"""Project management and coordination agents."""
|
|
309
|
+
|
|
310
|
+
DESIGN = "design"
|
|
311
|
+
"""UI/UX design and frontend agents."""
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
# Export all enums for convenient access
|
|
315
|
+
__all__ = [
|
|
316
|
+
"AgentCategory",
|
|
317
|
+
"ModelTier",
|
|
318
|
+
"OperationResult",
|
|
319
|
+
"OutputFormat",
|
|
320
|
+
"ServiceState",
|
|
321
|
+
"ValidationSeverity",
|
|
322
|
+
]
|
|
@@ -21,6 +21,7 @@ import threading
|
|
|
21
21
|
from datetime import datetime, timezone
|
|
22
22
|
from typing import Any, Dict, List, Optional
|
|
23
23
|
|
|
24
|
+
from ..core.enums import OperationResult
|
|
24
25
|
from ..core.logger import get_logger
|
|
25
26
|
|
|
26
27
|
|
|
@@ -158,7 +159,7 @@ class InstructionReinforcementHook:
|
|
|
158
159
|
# Create reminder todo
|
|
159
160
|
reminder_todo = {
|
|
160
161
|
"content": message,
|
|
161
|
-
"status":
|
|
162
|
+
"status": OperationResult.PENDING,
|
|
162
163
|
"activeForm": "Processing instruction reminder",
|
|
163
164
|
}
|
|
164
165
|
|
|
@@ -11,6 +11,7 @@ import uuid
|
|
|
11
11
|
from pathlib import Path
|
|
12
12
|
from typing import Any, Dict, Optional, Tuple
|
|
13
13
|
|
|
14
|
+
from claude_mpm.core.enums import ServiceState
|
|
14
15
|
from claude_mpm.core.logger import get_logger
|
|
15
16
|
|
|
16
17
|
|
|
@@ -179,7 +180,8 @@ class InteractiveSession:
|
|
|
179
180
|
# Notify WebSocket if connected
|
|
180
181
|
if self.runner.websocket_server:
|
|
181
182
|
self.runner.websocket_server.claude_status_changed(
|
|
182
|
-
status=
|
|
183
|
+
status=ServiceState.STARTING,
|
|
184
|
+
message="Launching Claude interactive session",
|
|
183
185
|
)
|
|
184
186
|
|
|
185
187
|
# Launch using selected method
|
|
@@ -454,7 +456,8 @@ class InteractiveSession:
|
|
|
454
456
|
# Notify WebSocket before exec
|
|
455
457
|
if self.runner.websocket_server:
|
|
456
458
|
self.runner.websocket_server.claude_status_changed(
|
|
457
|
-
status=
|
|
459
|
+
status=ServiceState.RUNNING,
|
|
460
|
+
message="Claude process started (exec mode)",
|
|
458
461
|
)
|
|
459
462
|
|
|
460
463
|
# This will not return if successful
|
|
@@ -494,7 +497,7 @@ class InteractiveSession:
|
|
|
494
497
|
# Notify WebSocket of error
|
|
495
498
|
if self.runner.websocket_server:
|
|
496
499
|
self.runner.websocket_server.claude_status_changed(
|
|
497
|
-
status=
|
|
500
|
+
status=ServiceState.ERROR, message=f"Failed to launch Claude: {error}"
|
|
498
501
|
)
|
|
499
502
|
|
|
500
503
|
def _handle_keyboard_interrupt(self) -> None:
|
|
@@ -24,6 +24,7 @@ from contextlib import contextmanager
|
|
|
24
24
|
from pathlib import Path
|
|
25
25
|
from typing import Any, Dict, Optional, Union
|
|
26
26
|
|
|
27
|
+
from claude_mpm.core.enums import OperationResult
|
|
27
28
|
from claude_mpm.core.logger import (
|
|
28
29
|
JsonFormatter,
|
|
29
30
|
finalize_streaming_logs,
|
|
@@ -234,7 +235,10 @@ def log_operation(
|
|
|
234
235
|
execution_time = time.time() - start_time
|
|
235
236
|
logger.info(
|
|
236
237
|
f"Completed {operation}",
|
|
237
|
-
extra={
|
|
238
|
+
extra={
|
|
239
|
+
"execution_time": execution_time,
|
|
240
|
+
"status": OperationResult.SUCCESS,
|
|
241
|
+
},
|
|
238
242
|
)
|
|
239
243
|
except Exception as e:
|
|
240
244
|
execution_time = time.time() - start_time
|
|
@@ -242,7 +246,7 @@ def log_operation(
|
|
|
242
246
|
f"Failed {operation}: {e}",
|
|
243
247
|
extra={
|
|
244
248
|
"execution_time": execution_time,
|
|
245
|
-
"status":
|
|
249
|
+
"status": OperationResult.FAILED,
|
|
246
250
|
"error": str(e),
|
|
247
251
|
},
|
|
248
252
|
)
|
|
@@ -12,6 +12,7 @@ import uuid
|
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any, Dict, Optional, Tuple
|
|
14
14
|
|
|
15
|
+
from claude_mpm.core.enums import OperationResult, ServiceState
|
|
15
16
|
from claude_mpm.core.logger import get_logger
|
|
16
17
|
|
|
17
18
|
|
|
@@ -162,7 +163,7 @@ class OneshotSession:
|
|
|
162
163
|
|
|
163
164
|
if self.runner.websocket_server:
|
|
164
165
|
self.runner.websocket_server.claude_status_changed(
|
|
165
|
-
status=
|
|
166
|
+
status=ServiceState.RUNNING, message="Executing Claude oneshot command"
|
|
166
167
|
)
|
|
167
168
|
|
|
168
169
|
def _run_subprocess(
|
|
@@ -222,7 +223,7 @@ class OneshotSession:
|
|
|
222
223
|
# End WebSocket session
|
|
223
224
|
if self.runner.websocket_server:
|
|
224
225
|
self.runner.websocket_server.claude_status_changed(
|
|
225
|
-
status=
|
|
226
|
+
status=ServiceState.STOPPED, message="Session completed"
|
|
226
227
|
)
|
|
227
228
|
self.runner.websocket_server.session_ended()
|
|
228
229
|
|
|
@@ -299,7 +300,9 @@ class OneshotSession:
|
|
|
299
300
|
agent_name = self.runner._extract_agent_from_response(response)
|
|
300
301
|
if agent_name:
|
|
301
302
|
self.runner.websocket_server.agent_delegated(
|
|
302
|
-
agent=agent_name,
|
|
303
|
+
agent=agent_name,
|
|
304
|
+
task=prompt[:100],
|
|
305
|
+
status=OperationResult.PENDING,
|
|
303
306
|
)
|
|
304
307
|
|
|
305
308
|
# Log completion
|
|
@@ -335,7 +338,8 @@ class OneshotSession:
|
|
|
335
338
|
if self.runner.websocket_server:
|
|
336
339
|
self.runner.websocket_server.claude_output(error_msg, "stderr")
|
|
337
340
|
self.runner.websocket_server.claude_status_changed(
|
|
338
|
-
status=
|
|
341
|
+
status=ServiceState.ERROR,
|
|
342
|
+
message=f"Command failed with code {return_code}",
|
|
339
343
|
)
|
|
340
344
|
|
|
341
345
|
# Log error
|
|
@@ -160,203 +160,23 @@ class OutputStyleManager:
|
|
|
160
160
|
|
|
161
161
|
def extract_output_style_content(self, framework_loader=None) -> str:
|
|
162
162
|
"""
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
This extracts PM delegation behavior, tone, communication standards,
|
|
166
|
-
response formats, TodoWrite requirements, and workflow rules from:
|
|
167
|
-
- INSTRUCTIONS.md
|
|
168
|
-
- BASE_PM.md
|
|
163
|
+
Read output style content from OUTPUT_STYLE.md.
|
|
169
164
|
|
|
170
165
|
Args:
|
|
171
|
-
framework_loader: Optional
|
|
166
|
+
framework_loader: Optional framework loader (kept for compatibility, not used)
|
|
172
167
|
|
|
173
168
|
Returns:
|
|
174
|
-
|
|
169
|
+
Complete output style content from file
|
|
175
170
|
"""
|
|
176
|
-
#
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
)
|
|
185
|
-
sections.append("---")
|
|
186
|
-
sections.append("")
|
|
187
|
-
|
|
188
|
-
# Header
|
|
189
|
-
sections.append(
|
|
190
|
-
"You are Claude Multi-Agent PM, a PROJECT MANAGER whose SOLE PURPOSE is to delegate work to specialized agents."
|
|
191
|
-
)
|
|
192
|
-
sections.append("")
|
|
193
|
-
|
|
194
|
-
# Extract from INSTRUCTIONS.md
|
|
195
|
-
if framework_loader and framework_loader.framework_content.get(
|
|
196
|
-
"framework_instructions"
|
|
197
|
-
):
|
|
198
|
-
instructions = framework_loader.framework_content["framework_instructions"]
|
|
199
|
-
sections.extend(self._extract_instructions_sections(instructions))
|
|
200
|
-
else:
|
|
201
|
-
# Load from file if no framework_loader provided
|
|
202
|
-
instructions_path = (
|
|
203
|
-
Path(__file__).parent.parent / "agents" / "INSTRUCTIONS.md"
|
|
204
|
-
)
|
|
205
|
-
if instructions_path.exists():
|
|
206
|
-
instructions = instructions_path.read_text()
|
|
207
|
-
sections.extend(self._extract_instructions_sections(instructions))
|
|
208
|
-
|
|
209
|
-
# Extract from BASE_PM.md
|
|
210
|
-
if framework_loader and framework_loader.framework_content.get(
|
|
211
|
-
"base_pm_instructions"
|
|
212
|
-
):
|
|
213
|
-
base_pm = framework_loader.framework_content["base_pm_instructions"]
|
|
214
|
-
sections.extend(self._extract_base_pm_sections(base_pm))
|
|
215
|
-
else:
|
|
216
|
-
# Load from file if no framework_loader provided
|
|
217
|
-
base_pm_path = Path(__file__).parent.parent / "agents" / "BASE_PM.md"
|
|
218
|
-
if base_pm_path.exists():
|
|
219
|
-
base_pm = base_pm_path.read_text()
|
|
220
|
-
sections.extend(self._extract_base_pm_sections(base_pm))
|
|
221
|
-
|
|
222
|
-
return "\n".join(sections)
|
|
223
|
-
|
|
224
|
-
def _extract_instructions_sections(self, content: str) -> list:
|
|
225
|
-
"""Extract relevant sections from INSTRUCTIONS.md."""
|
|
226
|
-
sections = []
|
|
227
|
-
|
|
228
|
-
# Extract Primary Directive
|
|
229
|
-
if "## 🔴 PRIMARY DIRECTIVE" in content:
|
|
230
|
-
sections.append("## 🔴 PRIMARY DIRECTIVE - MANDATORY DELEGATION 🔴")
|
|
231
|
-
sections.append("")
|
|
232
|
-
sections.append(
|
|
233
|
-
"**YOU ARE STRICTLY FORBIDDEN FROM DOING ANY WORK DIRECTLY.**"
|
|
234
|
-
)
|
|
235
|
-
sections.append("")
|
|
236
|
-
sections.append(
|
|
237
|
-
"Direct implementation is ABSOLUTELY PROHIBITED unless the user EXPLICITLY overrides with phrases like:"
|
|
238
|
-
)
|
|
239
|
-
sections.append('- "do this yourself"')
|
|
240
|
-
sections.append('- "don\'t delegate"')
|
|
241
|
-
sections.append('- "implement directly"')
|
|
242
|
-
sections.append('- "you do it"')
|
|
243
|
-
sections.append('- "no delegation"')
|
|
244
|
-
sections.append("")
|
|
245
|
-
|
|
246
|
-
# Extract Core Identity and Rules
|
|
247
|
-
if "## Core Identity" in content:
|
|
248
|
-
sections.append("## Core Operating Rules")
|
|
249
|
-
sections.append("")
|
|
250
|
-
sections.append("**DEFAULT BEHAVIOR - ALWAYS DELEGATE**:")
|
|
251
|
-
sections.append(
|
|
252
|
-
"- 🔴 You MUST delegate 100% of ALL work to specialized agents by default"
|
|
253
|
-
)
|
|
254
|
-
sections.append(
|
|
255
|
-
"- 🔴 Direct action is STRICTLY FORBIDDEN without explicit user override"
|
|
256
|
-
)
|
|
257
|
-
sections.append(
|
|
258
|
-
"- 🔴 Even the simplest tasks MUST be delegated - NO EXCEPTIONS"
|
|
259
|
-
)
|
|
260
|
-
sections.append("- 🔴 When in doubt, ALWAYS DELEGATE - never act directly")
|
|
261
|
-
sections.append("")
|
|
262
|
-
sections.append("**Allowed Tools**:")
|
|
263
|
-
sections.append("- **Task** for delegation (YOUR PRIMARY FUNCTION)")
|
|
264
|
-
sections.append("- **TodoWrite** for tracking delegation progress ONLY")
|
|
265
|
-
sections.append(
|
|
266
|
-
"- **WebSearch/WebFetch** for gathering context BEFORE delegation"
|
|
267
|
-
)
|
|
268
|
-
sections.append(
|
|
269
|
-
"- **Direct answers** ONLY for questions about PM capabilities"
|
|
270
|
-
)
|
|
271
|
-
sections.append("")
|
|
272
|
-
|
|
273
|
-
# Extract Communication Standards
|
|
274
|
-
if "## Communication Standards" in content:
|
|
275
|
-
sections.append("## Communication Standards")
|
|
276
|
-
sections.append("")
|
|
277
|
-
sections.append("- **Tone**: Professional, neutral by default")
|
|
278
|
-
sections.append('- **Use**: "Understood", "Confirmed", "Noted"')
|
|
279
|
-
sections.append("- **No simplification** without explicit user request")
|
|
280
|
-
sections.append("- **No mocks** outside test environments")
|
|
281
|
-
sections.append("- **Complete implementations** only - no placeholders")
|
|
282
|
-
sections.append(
|
|
283
|
-
'- **FORBIDDEN**: Overeager enthusiasm ("Excellent!", "Perfect!", "Amazing!")'
|
|
284
|
-
)
|
|
285
|
-
sections.append("")
|
|
286
|
-
|
|
287
|
-
# Extract Error Handling
|
|
288
|
-
if "## Error Handling Protocol" in content:
|
|
289
|
-
sections.append("## Error Handling Protocol")
|
|
290
|
-
sections.append("")
|
|
291
|
-
sections.append("**3-Attempt Process**:")
|
|
292
|
-
sections.append("1. **First Failure**: Re-delegate with enhanced context")
|
|
293
|
-
sections.append(
|
|
294
|
-
'2. **Second Failure**: Mark "ERROR - Attempt 2/3", escalate if needed'
|
|
295
|
-
)
|
|
296
|
-
sections.append(
|
|
297
|
-
"3. **Third Failure**: TodoWrite escalation with user decision required"
|
|
298
|
-
)
|
|
299
|
-
sections.append("")
|
|
300
|
-
|
|
301
|
-
# Extract Standard Operating Procedure
|
|
302
|
-
if "## Standard Operating Procedure" in content:
|
|
303
|
-
sections.append("## Standard Operating Procedure")
|
|
304
|
-
sections.append("")
|
|
305
|
-
sections.append("1. **Analysis**: Parse request, assess context (NO TOOLS)")
|
|
306
|
-
sections.append(
|
|
307
|
-
"2. **Planning**: Agent selection, task breakdown, priority assignment"
|
|
308
|
-
)
|
|
309
|
-
sections.append("3. **Delegation**: Task Tool with enhanced format")
|
|
310
|
-
sections.append("4. **Monitoring**: Track progress via TodoWrite")
|
|
311
|
-
sections.append("5. **Integration**: Synthesize results, validate, report")
|
|
312
|
-
sections.append("")
|
|
313
|
-
|
|
314
|
-
return sections
|
|
315
|
-
|
|
316
|
-
def _extract_base_pm_sections(self, content: str) -> list:
|
|
317
|
-
"""Extract relevant sections from BASE_PM.md."""
|
|
318
|
-
sections = []
|
|
319
|
-
|
|
320
|
-
# Extract TodoWrite Requirements
|
|
321
|
-
if "## TodoWrite Framework Requirements" in content:
|
|
322
|
-
sections.append("## TodoWrite Requirements")
|
|
323
|
-
sections.append("")
|
|
324
|
-
sections.append("### Mandatory [Agent] Prefix Rules")
|
|
325
|
-
sections.append("")
|
|
326
|
-
sections.append("**ALWAYS use [Agent] prefix for delegated tasks**:")
|
|
327
|
-
sections.append("- ✅ `[Research] Analyze authentication patterns`")
|
|
328
|
-
sections.append("- ✅ `[Engineer] Implement user registration`")
|
|
329
|
-
sections.append("- ✅ `[QA] Test payment flow`")
|
|
330
|
-
sections.append("- ✅ `[Documentation] Update API docs`")
|
|
331
|
-
sections.append("")
|
|
332
|
-
sections.append("**NEVER use [PM] prefix for implementation tasks**")
|
|
333
|
-
sections.append("")
|
|
334
|
-
sections.append("### Task Status Management")
|
|
335
|
-
sections.append("")
|
|
336
|
-
sections.append("- `pending` - Task not yet started")
|
|
337
|
-
sections.append(
|
|
338
|
-
"- `in_progress` - Currently being worked on (ONE at a time)"
|
|
339
|
-
)
|
|
340
|
-
sections.append("- `completed` - Task finished successfully")
|
|
341
|
-
sections.append("")
|
|
342
|
-
|
|
343
|
-
# Extract PM Response Format
|
|
344
|
-
if "## PM Response Format" in content:
|
|
345
|
-
sections.append("## Response Format")
|
|
346
|
-
sections.append("")
|
|
347
|
-
sections.append(
|
|
348
|
-
"When completing delegations, provide structured summaries including:"
|
|
349
|
-
)
|
|
350
|
-
sections.append("- Request summary")
|
|
351
|
-
sections.append("- Agents used and task counts")
|
|
352
|
-
sections.append("- Tasks completed with [Agent] prefixes")
|
|
353
|
-
sections.append("- Files affected across all agents")
|
|
354
|
-
sections.append("- Blockers encountered and resolutions")
|
|
355
|
-
sections.append("- Next steps for user")
|
|
356
|
-
sections.append("- Key information to remember")
|
|
357
|
-
sections.append("")
|
|
358
|
-
|
|
359
|
-
return sections
|
|
171
|
+
# Always read from the complete OUTPUT_STYLE.md file
|
|
172
|
+
if self.mpm_output_style_path.exists():
|
|
173
|
+
content = self.mpm_output_style_path.read_text()
|
|
174
|
+
self.logger.info(f"Read OUTPUT_STYLE.md directly ({len(content)} chars)")
|
|
175
|
+
return content
|
|
176
|
+
# Fallback error
|
|
177
|
+
error_msg = f"OUTPUT_STYLE.md not found at {self.mpm_output_style_path}"
|
|
178
|
+
self.logger.error(error_msg)
|
|
179
|
+
raise FileNotFoundError(error_msg)
|
|
360
180
|
|
|
361
181
|
def save_output_style(self, content: str) -> Path:
|
|
362
182
|
"""
|
|
@@ -10,6 +10,7 @@ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
|
|
|
10
10
|
from .base_service import BaseService
|
|
11
11
|
from .config import Config
|
|
12
12
|
from .container import DIContainer, ServiceLifetime, get_container
|
|
13
|
+
from .enums import OperationResult
|
|
13
14
|
from .logger import get_logger
|
|
14
15
|
from .shared.config_loader import ConfigLoader
|
|
15
16
|
|
|
@@ -249,7 +250,10 @@ class ServiceRegistry:
|
|
|
249
250
|
"metrics": health.metrics,
|
|
250
251
|
}
|
|
251
252
|
except Exception as e:
|
|
252
|
-
health_status[name] = {
|
|
253
|
+
health_status[name] = {
|
|
254
|
+
"status": OperationResult.ERROR,
|
|
255
|
+
"message": str(e),
|
|
256
|
+
}
|
|
253
257
|
|
|
254
258
|
return health_status
|
|
255
259
|
|