claude-mpm 3.4.27__py3-none-any.whl → 3.5.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 +1 -1
- claude_mpm/agents/INSTRUCTIONS.md +182 -299
- claude_mpm/agents/agent_loader.py +283 -57
- claude_mpm/agents/agent_loader_integration.py +6 -9
- claude_mpm/agents/base_agent.json +2 -1
- claude_mpm/agents/base_agent_loader.py +1 -1
- claude_mpm/cli/__init__.py +5 -7
- claude_mpm/cli/commands/__init__.py +0 -2
- claude_mpm/cli/commands/agents.py +1 -1
- claude_mpm/cli/commands/memory.py +1 -1
- claude_mpm/cli/commands/run.py +12 -0
- claude_mpm/cli/parser.py +0 -13
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/config/__init__.py +44 -2
- claude_mpm/config/agent_config.py +348 -0
- claude_mpm/config/paths.py +322 -0
- claude_mpm/constants.py +0 -1
- claude_mpm/core/__init__.py +2 -5
- claude_mpm/core/agent_registry.py +63 -17
- claude_mpm/core/claude_runner.py +354 -43
- claude_mpm/core/config.py +7 -1
- claude_mpm/core/config_aliases.py +4 -3
- claude_mpm/core/config_paths.py +151 -0
- claude_mpm/core/factories.py +4 -50
- claude_mpm/core/logger.py +11 -13
- claude_mpm/core/service_registry.py +2 -2
- claude_mpm/dashboard/static/js/components/agent-inference.js +101 -25
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -2
- claude_mpm/hooks/claude_hooks/hook_handler.py +343 -83
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/init.py +37 -6
- claude_mpm/scripts/socketio_daemon.py +6 -2
- claude_mpm/services/__init__.py +71 -3
- claude_mpm/services/agents/__init__.py +85 -0
- claude_mpm/services/agents/deployment/__init__.py +21 -0
- claude_mpm/services/{agent_deployment.py → agents/deployment/agent_deployment.py} +192 -41
- claude_mpm/services/{agent_lifecycle_manager.py → agents/deployment/agent_lifecycle_manager.py} +11 -10
- claude_mpm/services/agents/loading/__init__.py +11 -0
- claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +9 -8
- claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +2 -2
- claude_mpm/services/{framework_agent_loader.py → agents/loading/framework_agent_loader.py} +116 -40
- claude_mpm/services/agents/management/__init__.py +9 -0
- claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +6 -5
- claude_mpm/services/agents/memory/__init__.py +21 -0
- claude_mpm/services/{agent_memory_manager.py → agents/memory/agent_memory_manager.py} +3 -3
- claude_mpm/services/agents/registry/__init__.py +29 -0
- claude_mpm/services/{agent_registry.py → agents/registry/agent_registry.py} +101 -16
- claude_mpm/services/{deployed_agent_discovery.py → agents/registry/deployed_agent_discovery.py} +12 -2
- claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +6 -5
- claude_mpm/services/async_session_logger.py +584 -0
- claude_mpm/services/claude_session_logger.py +299 -0
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +17 -17
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +1 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +1 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +19 -24
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +1 -1
- claude_mpm/services/framework_claude_md_generator.py +4 -2
- claude_mpm/services/memory/__init__.py +17 -0
- claude_mpm/services/{memory_builder.py → memory/builder.py} +3 -3
- claude_mpm/services/memory/cache/__init__.py +14 -0
- claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +1 -1
- claude_mpm/services/memory/cache/simple_cache.py +317 -0
- claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +1 -1
- claude_mpm/services/{memory_router.py → memory/router.py} +1 -1
- claude_mpm/services/optimized_hook_service.py +542 -0
- claude_mpm/services/project_registry.py +14 -8
- claude_mpm/services/response_tracker.py +237 -0
- claude_mpm/services/ticketing_service_original.py +4 -2
- claude_mpm/services/version_control/branch_strategy.py +3 -1
- claude_mpm/utils/paths.py +12 -10
- claude_mpm/utils/session_logging.py +114 -0
- claude_mpm/validation/agent_validator.py +2 -1
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/RECORD +83 -106
- claude_mpm/cli/commands/ui.py +0 -57
- claude_mpm/core/simple_runner.py +0 -1046
- claude_mpm/hooks/builtin/__init__.py +0 -1
- claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
- claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
- claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
- claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
- claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
- claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
- claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
- claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
- claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
- claude_mpm/orchestration/__init__.py +0 -6
- claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
- claude_mpm/orchestration/archive/factory.py +0 -215
- claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
- claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
- claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
- claude_mpm/orchestration/archive/orchestrator.py +0 -501
- claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
- claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
- claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
- claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
- claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
- claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
- claude_mpm/schemas/workflow_validator.py +0 -411
- claude_mpm/services/parent_directory_manager/__init__.py +0 -577
- claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
- claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
- claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
- claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
- claude_mpm/services/parent_directory_manager/operations.py +0 -186
- claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
- claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
- claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
- claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
- claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
- claude_mpm/ui/__init__.py +0 -1
- claude_mpm/ui/rich_terminal_ui.py +0 -295
- claude_mpm/ui/terminal_ui.py +0 -328
- /claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +0 -0
- /claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +0 -0
- /claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.27.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Claude Session Response Logger
|
|
3
|
+
|
|
4
|
+
Simplified response logging system that uses Claude Code session IDs.
|
|
5
|
+
Stores responses in docs/responses/{session-id}/ for easy access.
|
|
6
|
+
|
|
7
|
+
Now with optional async logging support for improved performance.
|
|
8
|
+
Configuration via .claude-mpm/configuration.yaml.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from datetime import datetime
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Dict, Any, Optional
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
# Import configuration manager
|
|
19
|
+
from claude_mpm.core.config import Config
|
|
20
|
+
|
|
21
|
+
# Try to import async logger for performance optimization
|
|
22
|
+
try:
|
|
23
|
+
from claude_mpm.services.async_session_logger import (
|
|
24
|
+
get_async_logger,
|
|
25
|
+
log_response_async,
|
|
26
|
+
AsyncSessionLogger
|
|
27
|
+
)
|
|
28
|
+
ASYNC_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
ASYNC_AVAILABLE = False
|
|
31
|
+
|
|
32
|
+
logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ClaudeSessionLogger:
|
|
36
|
+
"""Simplified response logger for Claude Code sessions."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, base_dir: Optional[Path] = None, use_async: Optional[bool] = None, config: Optional[Config] = None):
|
|
39
|
+
"""
|
|
40
|
+
Initialize the session logger.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
base_dir: Base directory for responses. Overrides config.
|
|
44
|
+
use_async: Use async logging if available. Overrides config.
|
|
45
|
+
config: Configuration instance to use (creates new if not provided)
|
|
46
|
+
"""
|
|
47
|
+
# Load configuration
|
|
48
|
+
if config is None:
|
|
49
|
+
config = Config()
|
|
50
|
+
self.config = config
|
|
51
|
+
|
|
52
|
+
# Get response logging configuration
|
|
53
|
+
response_config = self.config.get('response_logging', {})
|
|
54
|
+
|
|
55
|
+
# Determine base directory
|
|
56
|
+
if base_dir is None:
|
|
57
|
+
# Check configuration first
|
|
58
|
+
base_dir = response_config.get('session_directory')
|
|
59
|
+
if not base_dir:
|
|
60
|
+
# Fall back to default response directory
|
|
61
|
+
base_dir = '.claude-mpm/responses'
|
|
62
|
+
base_dir = Path(base_dir)
|
|
63
|
+
|
|
64
|
+
self.base_dir = Path(base_dir)
|
|
65
|
+
self.base_dir.mkdir(parents=True, exist_ok=True)
|
|
66
|
+
|
|
67
|
+
# Try to get session ID from environment
|
|
68
|
+
self.session_id = self._get_claude_session_id()
|
|
69
|
+
self.response_counter = {} # Track response count per session
|
|
70
|
+
|
|
71
|
+
# Determine if we should use async logging
|
|
72
|
+
if use_async is None:
|
|
73
|
+
# Check if response logging is enabled at all
|
|
74
|
+
if not response_config.get('enabled', True):
|
|
75
|
+
logger.info("Response logging disabled in configuration")
|
|
76
|
+
use_async = False
|
|
77
|
+
else:
|
|
78
|
+
# Check configuration for async preference
|
|
79
|
+
use_async = response_config.get('use_async', True)
|
|
80
|
+
|
|
81
|
+
# Check environment for backward compatibility
|
|
82
|
+
if os.environ.get('CLAUDE_USE_ASYNC_LOG'):
|
|
83
|
+
env_async = os.environ.get('CLAUDE_USE_ASYNC_LOG', 'true').lower() == 'true'
|
|
84
|
+
logger.info(f"Using CLAUDE_USE_ASYNC_LOG environment variable (deprecated): {env_async}")
|
|
85
|
+
use_async = env_async
|
|
86
|
+
|
|
87
|
+
self.use_async = use_async and ASYNC_AVAILABLE
|
|
88
|
+
self._async_logger = None
|
|
89
|
+
|
|
90
|
+
if self.use_async:
|
|
91
|
+
try:
|
|
92
|
+
self._async_logger = get_async_logger(config=config)
|
|
93
|
+
logger.info("Using async logger for improved performance")
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.warning(f"Failed to initialize async logger, falling back to sync: {e}")
|
|
96
|
+
self.use_async = False
|
|
97
|
+
|
|
98
|
+
def _get_claude_session_id(self) -> Optional[str]:
|
|
99
|
+
"""
|
|
100
|
+
Get the Claude Code session ID from environment.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Session ID if available, None otherwise
|
|
104
|
+
"""
|
|
105
|
+
# Claude Code may set various environment variables
|
|
106
|
+
# Check common patterns
|
|
107
|
+
session_id = None
|
|
108
|
+
|
|
109
|
+
# Check for CLAUDE_SESSION_ID
|
|
110
|
+
session_id = os.environ.get('CLAUDE_SESSION_ID')
|
|
111
|
+
|
|
112
|
+
# Check for ANTHROPIC_SESSION_ID
|
|
113
|
+
if not session_id:
|
|
114
|
+
session_id = os.environ.get('ANTHROPIC_SESSION_ID')
|
|
115
|
+
|
|
116
|
+
# Check for generic SESSION_ID
|
|
117
|
+
if not session_id:
|
|
118
|
+
session_id = os.environ.get('SESSION_ID')
|
|
119
|
+
|
|
120
|
+
# Generate a default based on timestamp if nothing found
|
|
121
|
+
if not session_id:
|
|
122
|
+
# Use a timestamp-based session ID as fallback
|
|
123
|
+
session_id = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
124
|
+
logger.info(f"No Claude session ID found, using generated: {session_id}")
|
|
125
|
+
else:
|
|
126
|
+
logger.info(f"Using Claude session ID: {session_id}")
|
|
127
|
+
|
|
128
|
+
return session_id
|
|
129
|
+
|
|
130
|
+
def _generate_filename(self, agent: Optional[str] = None) -> str:
|
|
131
|
+
"""
|
|
132
|
+
Generate a flat filename with session ID, agent, and timestamp.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
agent: Optional agent name
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Filename in format: [session_id]-[agent]-timestamp.json
|
|
139
|
+
"""
|
|
140
|
+
# Get agent name, defaulting to "unknown" if not provided
|
|
141
|
+
agent_name = agent or "unknown"
|
|
142
|
+
# Sanitize agent name (replace spaces with underscores, lowercase)
|
|
143
|
+
agent_name = agent_name.replace(" ", "_").lower()
|
|
144
|
+
|
|
145
|
+
# Generate timestamp with microseconds for uniqueness
|
|
146
|
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
|
147
|
+
|
|
148
|
+
# Create filename: session_id-agent-timestamp.json
|
|
149
|
+
filename = f"{self.session_id}-{agent_name}-{timestamp}.json"
|
|
150
|
+
return filename
|
|
151
|
+
|
|
152
|
+
def log_response(
|
|
153
|
+
self,
|
|
154
|
+
request_summary: str,
|
|
155
|
+
response_content: str,
|
|
156
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
157
|
+
agent: Optional[str] = None
|
|
158
|
+
) -> Optional[Path]:
|
|
159
|
+
"""
|
|
160
|
+
Log a response to the session directory.
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
request_summary: Brief summary of the request
|
|
164
|
+
response_content: The full response content
|
|
165
|
+
metadata: Optional metadata (agent name, model, etc.)
|
|
166
|
+
agent: Optional agent name (overrides metadata)
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Path to the saved response file, or None if disabled
|
|
170
|
+
"""
|
|
171
|
+
# Check if logging is actually enabled
|
|
172
|
+
response_config = self.config.get('response_logging', {})
|
|
173
|
+
if not response_config.get('enabled', True):
|
|
174
|
+
logger.debug("Response logging is disabled in configuration")
|
|
175
|
+
return None
|
|
176
|
+
|
|
177
|
+
if not self.session_id:
|
|
178
|
+
return None
|
|
179
|
+
|
|
180
|
+
# Use async logger if available for better performance
|
|
181
|
+
if self.use_async and self._async_logger:
|
|
182
|
+
success = self._async_logger.log_response(
|
|
183
|
+
request_summary=request_summary,
|
|
184
|
+
response_content=response_content,
|
|
185
|
+
metadata=metadata,
|
|
186
|
+
agent=agent
|
|
187
|
+
)
|
|
188
|
+
if success:
|
|
189
|
+
# Return expected path for compatibility
|
|
190
|
+
# Async logger uses timestamp-based names, so we can't return exact path
|
|
191
|
+
return self.base_dir / "async_response.json"
|
|
192
|
+
return None
|
|
193
|
+
|
|
194
|
+
# Fall back to synchronous logging
|
|
195
|
+
# Ensure base directory exists (flat structure, no subdirs)
|
|
196
|
+
self.base_dir.mkdir(parents=True, exist_ok=True)
|
|
197
|
+
|
|
198
|
+
# Extract agent name from parameter or metadata
|
|
199
|
+
agent_name = agent or (metadata.get("agent") if metadata else None) or "unknown"
|
|
200
|
+
|
|
201
|
+
# Generate filename with flat structure
|
|
202
|
+
filename = self._generate_filename(agent_name)
|
|
203
|
+
file_path = self.base_dir / filename
|
|
204
|
+
|
|
205
|
+
# Prepare response data with standardized field names
|
|
206
|
+
response_data = {
|
|
207
|
+
"timestamp": datetime.now().isoformat(),
|
|
208
|
+
"session_id": self.session_id,
|
|
209
|
+
"request": request_summary, # Standardized field name
|
|
210
|
+
"response": response_content, # Already correct
|
|
211
|
+
"agent": agent or (metadata.get("agent") if metadata else None) or "unknown", # Standardized field name
|
|
212
|
+
"metadata": metadata or {}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Save response
|
|
216
|
+
try:
|
|
217
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
218
|
+
json.dump(response_data, f, indent=2, ensure_ascii=False)
|
|
219
|
+
|
|
220
|
+
logger.debug(f"Logged response to {filename} for session {self.session_id}")
|
|
221
|
+
return file_path
|
|
222
|
+
|
|
223
|
+
except Exception as e:
|
|
224
|
+
logger.error(f"Failed to log response: {e}")
|
|
225
|
+
return None
|
|
226
|
+
|
|
227
|
+
def set_session_id(self, session_id: str) -> None:
|
|
228
|
+
"""
|
|
229
|
+
Manually set the session ID.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
session_id: The session ID to use
|
|
233
|
+
"""
|
|
234
|
+
self.session_id = session_id
|
|
235
|
+
logger.info(f"Session ID set to: {session_id}")
|
|
236
|
+
|
|
237
|
+
def get_session_path(self) -> Optional[Path]:
|
|
238
|
+
"""
|
|
239
|
+
Get the path to the responses directory.
|
|
240
|
+
|
|
241
|
+
Note: With flat structure, returns the base directory.
|
|
242
|
+
|
|
243
|
+
Returns:
|
|
244
|
+
Path to responses directory, or None if no session
|
|
245
|
+
"""
|
|
246
|
+
if not self.session_id:
|
|
247
|
+
return None
|
|
248
|
+
return self.base_dir
|
|
249
|
+
|
|
250
|
+
def is_enabled(self) -> bool:
|
|
251
|
+
"""
|
|
252
|
+
Check if logging is enabled.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
True if logging is enabled (session ID available)
|
|
256
|
+
"""
|
|
257
|
+
return self.session_id is not None
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
# Singleton instance for easy access
|
|
261
|
+
_logger_instance = None
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def get_session_logger(config: Optional[Config] = None) -> ClaudeSessionLogger:
|
|
265
|
+
"""
|
|
266
|
+
Get the singleton session logger instance.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
config: Optional configuration instance to use
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
The shared ClaudeSessionLogger instance
|
|
273
|
+
"""
|
|
274
|
+
global _logger_instance
|
|
275
|
+
if _logger_instance is None:
|
|
276
|
+
_logger_instance = ClaudeSessionLogger(config=config)
|
|
277
|
+
return _logger_instance
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def log_response(
|
|
281
|
+
request_summary: str,
|
|
282
|
+
response_content: str,
|
|
283
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
284
|
+
agent: Optional[str] = None
|
|
285
|
+
) -> Optional[Path]:
|
|
286
|
+
"""
|
|
287
|
+
Convenience function to log a response.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
request_summary: Brief summary of the request
|
|
291
|
+
response_content: The full response content
|
|
292
|
+
metadata: Optional metadata
|
|
293
|
+
agent: Optional agent name
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
Path to the saved response file
|
|
297
|
+
"""
|
|
298
|
+
logger = get_session_logger()
|
|
299
|
+
return logger.log_response(request_summary, response_content, metadata, agent)
|
|
@@ -10,8 +10,8 @@ from typing import Dict, List, Optional, Any
|
|
|
10
10
|
from collections import OrderedDict
|
|
11
11
|
import logging
|
|
12
12
|
|
|
13
|
-
from claude_mpm.services.
|
|
14
|
-
from claude_mpm.services.
|
|
13
|
+
from claude_mpm.services.agents.registry import DeployedAgentDiscovery
|
|
14
|
+
from claude_mpm.services.agents.management import AgentCapabilitiesGenerator
|
|
15
15
|
|
|
16
16
|
logger = logging.getLogger(__name__)
|
|
17
17
|
|
|
@@ -75,15 +75,15 @@ class AgentsGenerator(BaseSectionGenerator):
|
|
|
75
75
|
**ALL AGENT OPERATIONS FOLLOW HIERARCHICAL PRECEDENCE**
|
|
76
76
|
|
|
77
77
|
#### Agent Hierarchy (Highest to Lowest Priority)
|
|
78
|
-
1. **Project Agents**: `$PROJECT/.claude-
|
|
78
|
+
1. **Project Agents**: `$PROJECT/.claude-mpm/agents/project-specific/`
|
|
79
79
|
- Project-specific implementations and overrides
|
|
80
80
|
- Highest precedence for project context
|
|
81
81
|
- Custom agents tailored to project requirements
|
|
82
82
|
|
|
83
83
|
2. **User Agents**: Directory hierarchy with precedence walking
|
|
84
|
-
- **Current Directory**: `$PWD/.claude-
|
|
84
|
+
- **Current Directory**: `$PWD/.claude-mpm/agents/user-agents/` (highest user precedence)
|
|
85
85
|
- **Parent Directories**: Walk up tree checking `../user-agents/`, `../../user-agents/`, etc.
|
|
86
|
-
- **User Home**: `~/.claude-
|
|
86
|
+
- **User Home**: `~/.claude-mpm/agents/user-defined/` (fallback user location)
|
|
87
87
|
- User-specific customizations across projects
|
|
88
88
|
- Mid-priority, can override system defaults
|
|
89
89
|
|
|
@@ -258,7 +258,7 @@ task_type = "performance_optimization"
|
|
|
258
258
|
required_specializations = ["performance", "monitoring"]
|
|
259
259
|
|
|
260
260
|
# Discover optimal agent
|
|
261
|
-
all_agents = registry.
|
|
261
|
+
all_agents = registry.list_agents()
|
|
262
262
|
# Filter by specializations
|
|
263
263
|
optimal_agents = {k: v for k, v in all_agents.items()
|
|
264
264
|
if any(spec in v.get('specializations', [])
|
|
@@ -352,7 +352,7 @@ TEMPORAL CONTEXT: Today is [date]. Apply date awareness to data operations.
|
|
|
352
352
|
|
|
353
353
|
**CRITICAL: Agent Registry provides dynamic agent discovery beyond core 9 agent types**
|
|
354
354
|
|
|
355
|
-
#### AgentRegistry.
|
|
355
|
+
#### AgentRegistry.list_agents() Method Usage
|
|
356
356
|
|
|
357
357
|
**Comprehensive Agent Discovery API:**
|
|
358
358
|
```python
|
|
@@ -362,7 +362,7 @@ from claude_pm.core.agent_registry import AgentRegistry
|
|
|
362
362
|
registry = AgentRegistry()
|
|
363
363
|
|
|
364
364
|
# List all available agents with metadata
|
|
365
|
-
agents = registry.
|
|
365
|
+
agents = registry.list_agents()
|
|
366
366
|
|
|
367
367
|
# Access agent metadata
|
|
368
368
|
for agent_id, metadata in agents.items():
|
|
@@ -376,15 +376,15 @@ for agent_id, metadata in agents.items():
|
|
|
376
376
|
#### Directory Precedence Rules and Agent Discovery
|
|
377
377
|
|
|
378
378
|
**Enhanced Agent Discovery Pattern (Highest to Lowest Priority):**
|
|
379
|
-
1. **Project Agents**: `$PROJECT/.claude-
|
|
380
|
-
2. **Current Directory User Agents**: `$PWD/.claude-
|
|
379
|
+
1. **Project Agents**: `$PROJECT/.claude-mpm/agents/project-specific/`
|
|
380
|
+
2. **Current Directory User Agents**: `$PWD/.claude-mpm/agents/user-agents/`
|
|
381
381
|
3. **Parent Directory User Agents**: Walk up tree checking `../user-agents/`, `../../user-agents/`, etc.
|
|
382
|
-
4. **User Home Agents**: `~/.claude-
|
|
382
|
+
4. **User Home Agents**: `~/.claude-mpm/agents/user-defined/`
|
|
383
383
|
5. **System Agents**: `claude_pm/agents/`
|
|
384
384
|
|
|
385
385
|
**User-Agents Directory Structure:**
|
|
386
386
|
```
|
|
387
|
-
$PWD/.claude-
|
|
387
|
+
$PWD/.claude-mpm/agents/user-agents/
|
|
388
388
|
├── specialized/
|
|
389
389
|
│ ├── performance-agent.md
|
|
390
390
|
│ ├── architecture-agent.md
|
|
@@ -403,7 +403,7 @@ $PWD/.claude-pm/agents/user-agents/
|
|
|
403
403
|
registry = AgentRegistry()
|
|
404
404
|
|
|
405
405
|
# Discover all agents
|
|
406
|
-
all_agents = registry.
|
|
406
|
+
all_agents = registry.list_agents()
|
|
407
407
|
|
|
408
408
|
# Filter by tier if needed
|
|
409
409
|
project_agents = {k: v for k, v in all_agents.items() if v.get('tier') == 'project'}
|
|
@@ -420,7 +420,7 @@ system_agents = {k: v for k, v in all_agents.items() if v.get('tier') == 'system
|
|
|
420
420
|
**Specialized Discovery Usage:**
|
|
421
421
|
```python
|
|
422
422
|
# Discover agents by type (note: specialization filtering would require custom filtering)
|
|
423
|
-
all_agents = registry.
|
|
423
|
+
all_agents = registry.list_agents()
|
|
424
424
|
|
|
425
425
|
# Filter by specialization manually
|
|
426
426
|
ui_agents = {k: v for k, v in all_agents.items() if 'ui_ux' in v.get('specializations', [])}
|
|
@@ -440,7 +440,7 @@ multi_spec = {k: v for k, v in all_agents.items()
|
|
|
440
440
|
registry = AgentRegistry()
|
|
441
441
|
|
|
442
442
|
# Get all agents (modification timestamps are included by default)
|
|
443
|
-
agents_with_tracking = registry.
|
|
443
|
+
agents_with_tracking = registry.list_agents()
|
|
444
444
|
|
|
445
445
|
# Filter agents modified since last orchestration manually
|
|
446
446
|
recent_agents = {k: v for k, v in agents_with_tracking.items()
|
|
@@ -464,7 +464,7 @@ cache = SharedPromptCache()
|
|
|
464
464
|
registry = AgentRegistry(prompt_cache=cache)
|
|
465
465
|
|
|
466
466
|
# Agent discovery (caching is automatic)
|
|
467
|
-
cached_agents = registry.
|
|
467
|
+
cached_agents = registry.list_agents()
|
|
468
468
|
|
|
469
469
|
# Cache optimization for repeated orchestration
|
|
470
470
|
cache.preload_agent_prompts(agent_ids=['documentation', 'qa', 'engineer'])
|
|
@@ -486,7 +486,7 @@ def select_optimal_agent(task_type, specialization_requirements):
|
|
|
486
486
|
registry = AgentRegistry()
|
|
487
487
|
|
|
488
488
|
# Find agents matching requirements
|
|
489
|
-
all_agents = registry.
|
|
489
|
+
all_agents = registry.list_agents()
|
|
490
490
|
matching_agents = {k: v for k, v in all_agents.items()
|
|
491
491
|
if any(spec in v.get('specializations', [])
|
|
492
492
|
for spec in specialization_requirements)}
|
|
@@ -541,7 +541,7 @@ TEMPORAL CONTEXT: Today is [date]. Using agent registry for optimal agent select
|
|
|
541
541
|
|
|
542
542
|
**Enhanced Orchestration with Dynamic Discovery:**
|
|
543
543
|
|
|
544
|
-
1. **Dynamic Agent Selection**: Use AgentRegistry.
|
|
544
|
+
1. **Dynamic Agent Selection**: Use AgentRegistry.list_agents() to select optimal agents based on task requirements and available specializations
|
|
545
545
|
|
|
546
546
|
2. **Precedence-Aware Delegation**: Respect directory precedence when multiple agents of same type exist
|
|
547
547
|
|
|
@@ -562,7 +562,7 @@ def orchestrate_with_registry(task_description, requirements):
|
|
|
562
562
|
registry = AgentRegistry()
|
|
563
563
|
|
|
564
564
|
# Discover optimal agents
|
|
565
|
-
all_agents = registry.
|
|
565
|
+
all_agents = registry.list_agents()
|
|
566
566
|
# Filter by requirements
|
|
567
567
|
agents = {k: v for k, v in all_agents.items()
|
|
568
568
|
if any(spec in v.get('specializations', [])
|
|
@@ -70,15 +70,15 @@ claude-pm init --verify
|
|
|
70
70
|
|
|
71
71
|
**Multi-Project Orchestrator Pattern:**
|
|
72
72
|
|
|
73
|
-
1. **Framework Directory** (`/Users/masa/Projects/claude-multiagent-pm/.claude-
|
|
73
|
+
1. **Framework Directory** (`/Users/masa/Projects/claude-multiagent-pm/.claude-mpm/`)
|
|
74
74
|
- Global user agents (shared across all projects)
|
|
75
75
|
- Framework-level configuration
|
|
76
76
|
|
|
77
|
-
2. **Working Directory** (`$PWD/.claude-
|
|
77
|
+
2. **Working Directory** (`$PWD/.claude-mpm/`)
|
|
78
78
|
- Current session configuration
|
|
79
79
|
- Working directory context
|
|
80
80
|
|
|
81
|
-
3. **Project Directory** (`$PROJECT_ROOT/.claude-
|
|
81
|
+
3. **Project Directory** (`$PROJECT_ROOT/.claude-mpm/`)
|
|
82
82
|
- Project-specific agents in `agents/project-specific/`
|
|
83
83
|
- User agents in `agents/user-agents/` with directory precedence
|
|
84
84
|
- Project-specific configuration
|
claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py
CHANGED
|
@@ -16,7 +16,7 @@ class CoreResponsibilitiesGenerator(BaseSectionGenerator):
|
|
|
16
16
|
1. **Framework Initialization**: MANDATORY claude-pm init verification and three-tier agent hierarchy setup
|
|
17
17
|
2. **Date Awareness**: Always acknowledge current date at session start and maintain temporal context
|
|
18
18
|
3. **Core System Validation**: Verify core system health and ensure operational stability
|
|
19
|
-
4. **Agent Registry Integration**: Use AgentRegistry.
|
|
19
|
+
4. **Agent Registry Integration**: Use AgentRegistry.list_agents() for dynamic agent discovery and optimal task delegation
|
|
20
20
|
5. **Core Agent Orchestration**: MANDATORY collaboration with all 9 core agent types (Documentation, Ticketing, Version Control, QA, Research, Ops, Security, Engineer, Data Engineer) via Task Tool
|
|
21
21
|
6. **Specialized Agent Discovery**: Leverage agent registry for 35+ specialized agent types beyond core 9
|
|
22
22
|
7. **Multi-Agent Coordination**: Coordinate agents using three-tier hierarchy via Task Tool with registry-enhanced selection
|
claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py
CHANGED
|
@@ -22,7 +22,7 @@ class OrchestrationPrinciplesGenerator(BaseSectionGenerator):
|
|
|
22
22
|
6. **Cross-Agent Coordination**: Orchestrate workflows that span multiple agents with proper sequencing
|
|
23
23
|
7. **TodoWrite Integration**: Use TodoWrite to track and coordinate complex multi-agent workflows
|
|
24
24
|
8. **Operation Tracking**: Systematic capture of operational insights and project patterns
|
|
25
|
-
9. **Agent Registry Integration**: Use AgentRegistry.
|
|
25
|
+
9. **Agent Registry Integration**: Use AgentRegistry.list_agents() for dynamic agent discovery and optimal task delegation
|
|
26
26
|
10. **Precedence-Aware Orchestration**: Respect directory precedence (project → user → system) when selecting agents
|
|
27
27
|
11. **Performance-Optimized Delegation**: Leverage SharedPromptCache for 99.7% faster agent loading and orchestration
|
|
28
28
|
12. **Specialization-Based Routing**: Route tasks to agents with appropriate specializations beyond core 9 types using registry discovery
|
|
@@ -43,38 +43,33 @@ class TodoTaskToolsGenerator(BaseSectionGenerator):
|
|
|
43
43
|
Task(description="[task description]", subagent_type="[agent-type]")
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
**Valid subagent_type values (
|
|
46
|
+
**Valid subagent_type values (use lowercase format for Claude Code compatibility):**
|
|
47
47
|
|
|
48
|
-
**
|
|
48
|
+
**Required lowercase format (Claude Code expects these exact values):**
|
|
49
49
|
- `subagent_type="research"` - For investigation and analysis
|
|
50
50
|
- `subagent_type="engineer"` - For coding and implementation
|
|
51
51
|
- `subagent_type="qa"` - For testing and quality assurance
|
|
52
52
|
- `subagent_type="documentation"` - For docs and guides
|
|
53
53
|
- `subagent_type="security"` - For security assessments
|
|
54
54
|
- `subagent_type="ops"` - For deployment and infrastructure
|
|
55
|
-
- `subagent_type="
|
|
56
|
-
- `subagent_type="
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- `subagent_type="Security"` - For security assessments
|
|
64
|
-
- `subagent_type="Ops"` - For deployment and infrastructure
|
|
65
|
-
- `subagent_type="Version Control"` - For git and version management
|
|
66
|
-
- `subagent_type="Data Engineer"` - For data processing and APIs
|
|
67
|
-
|
|
68
|
-
**Examples of Proper Task Tool Usage (both formats work):**
|
|
55
|
+
- `subagent_type="version_control"` - For git and version management (use underscore, not hyphen)
|
|
56
|
+
- `subagent_type="data_engineer"` - For data processing and APIs (use underscore, not hyphen)
|
|
57
|
+
- `subagent_type="pm"` - For project management coordination
|
|
58
|
+
- `subagent_type="test_integration"` - For integration testing
|
|
59
|
+
|
|
60
|
+
**Note:** Claude Code's Task tool requires exact lowercase agent names. Capitalized formats like "Research" or "Engineer" will be rejected with an error.
|
|
61
|
+
|
|
62
|
+
**Examples of Proper Task Tool Usage (use lowercase format only):**
|
|
69
63
|
- ✅ `Task(description="Update framework documentation", subagent_type="documentation")`
|
|
70
64
|
- ✅ `Task(description="Execute test suite validation", subagent_type="qa")`
|
|
71
|
-
- ✅ `Task(description="Create feature branch and sync", subagent_type="
|
|
65
|
+
- ✅ `Task(description="Create feature branch and sync", subagent_type="version_control")` (use underscore)
|
|
72
66
|
- ✅ `Task(description="Investigate performance patterns", subagent_type="research")`
|
|
73
67
|
- ✅ `Task(description="Implement authentication system", subagent_type="engineer")`
|
|
74
|
-
- ✅ `Task(description="Configure database and optimize queries", subagent_type="
|
|
75
|
-
- ✅ `Task(description="
|
|
76
|
-
-
|
|
77
|
-
-
|
|
68
|
+
- ✅ `Task(description="Configure database and optimize queries", subagent_type="data_engineer")` (use underscore)
|
|
69
|
+
- ✅ `Task(description="Coordinate project tasks", subagent_type="pm")`
|
|
70
|
+
- ❌ `Task(description="Analyze code patterns", subagent_type="Research")` (WRONG - will be rejected)
|
|
71
|
+
- ❌ `Task(description="Update API docs", subagent_type="Documentation")` (WRONG - will be rejected)
|
|
72
|
+
- ❌ `Task(description="Create release tags", subagent_type="Version Control")` (WRONG - will be rejected)
|
|
78
73
|
|
|
79
74
|
### 🚨 MANDATORY: THREE SHORTCUT COMMANDS
|
|
80
75
|
|
|
@@ -103,11 +98,11 @@ Task(description="[task description]", subagent_type="[agent-type]")
|
|
|
103
98
|
- ☐ [Data Engineer] Validate data integrity and verify API connectivity
|
|
104
99
|
- ☐ [Version Control] Apply semantic version bump and create release tags
|
|
105
100
|
|
|
106
|
-
# Corresponding Task Tool delegations:
|
|
101
|
+
# Corresponding Task Tool delegations (use lowercase with underscores):
|
|
107
102
|
Task(description="Generate changelog and analyze version impact", subagent_type="documentation")
|
|
108
103
|
Task(description="Execute full test suite and quality validation", subagent_type="qa")
|
|
109
|
-
Task(description="Validate data integrity and verify API connectivity", subagent_type="
|
|
110
|
-
Task(description="Apply semantic version bump and create release tags", subagent_type="
|
|
104
|
+
Task(description="Validate data integrity and verify API connectivity", subagent_type="data_engineer")
|
|
105
|
+
Task(description="Apply semantic version bump and create release tags", subagent_type="version_control")
|
|
111
106
|
|
|
112
107
|
# Update TodoWrite status based on agent completions
|
|
113
108
|
```
|
|
@@ -21,7 +21,7 @@ class TroubleshootingGenerator(BaseSectionGenerator):
|
|
|
21
21
|
4. **Permission Issues**: Ensure proper file permissions on CLI executables
|
|
22
22
|
|
|
23
23
|
### claude-pm init and Agent Hierarchy Issues
|
|
24
|
-
5. **Missing .claude-
|
|
24
|
+
5. **Missing .claude-mpm Directories**: Run `claude-pm init --setup`
|
|
25
25
|
6. **Agent Hierarchy Validation Errors**: Run `claude-pm init --verify` for detailed validation
|
|
26
26
|
|
|
27
27
|
### Core System Issues
|
|
@@ -18,6 +18,8 @@ from pathlib import Path
|
|
|
18
18
|
from typing import Dict, Optional, Any, List, Tuple, Callable
|
|
19
19
|
from dataclasses import dataclass, field
|
|
20
20
|
|
|
21
|
+
from claude_mpm.core.config_paths import ConfigPaths
|
|
22
|
+
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
23
25
|
|
|
@@ -338,7 +340,7 @@ class FrameworkClaudeMdGenerator:
|
|
|
338
340
|
self.framework_root = self._find_framework_root()
|
|
339
341
|
self.deployment_targets = {
|
|
340
342
|
'framework': self.framework_root / 'INSTRUCTIONS.md' if self.framework_root else None,
|
|
341
|
-
'user':
|
|
343
|
+
'user': ConfigPaths.get_user_config_dir() / 'INSTRUCTIONS.md',
|
|
342
344
|
'project': Path.cwd() / 'INSTRUCTIONS.md'
|
|
343
345
|
}
|
|
344
346
|
|
|
@@ -353,7 +355,7 @@ class FrameworkClaudeMdGenerator:
|
|
|
353
355
|
version_locations = [
|
|
354
356
|
Path(__file__).parent.parent / 'framework' / 'VERSION',
|
|
355
357
|
Path.cwd() / 'framework' / 'VERSION',
|
|
356
|
-
|
|
358
|
+
ConfigPaths.get_user_config_dir() / 'VERSION'
|
|
357
359
|
]
|
|
358
360
|
|
|
359
361
|
for version_file in version_locations:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Memory services for Claude MPM.
|
|
2
|
+
|
|
3
|
+
This module provides memory management services including:
|
|
4
|
+
- Memory building and optimization
|
|
5
|
+
- Memory routing to appropriate agents
|
|
6
|
+
- Caching services for performance
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from .builder import MemoryBuilder
|
|
10
|
+
from .router import MemoryRouter
|
|
11
|
+
from .optimizer import MemoryOptimizer
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"MemoryBuilder",
|
|
15
|
+
"MemoryRouter",
|
|
16
|
+
"MemoryOptimizer",
|
|
17
|
+
]
|
|
@@ -28,10 +28,10 @@ from pathlib import Path
|
|
|
28
28
|
from typing import Dict, List, Optional, Any, Tuple
|
|
29
29
|
from datetime import datetime
|
|
30
30
|
|
|
31
|
-
from claude_mpm.core import LoggerMixin
|
|
31
|
+
from claude_mpm.core.mixins import LoggerMixin
|
|
32
32
|
from claude_mpm.core.config import Config
|
|
33
33
|
from claude_mpm.utils.paths import PathResolver
|
|
34
|
-
from claude_mpm.services.
|
|
34
|
+
from claude_mpm.services.memory.router import MemoryRouter
|
|
35
35
|
from claude_mpm.services.project_analyzer import ProjectAnalyzer
|
|
36
36
|
|
|
37
37
|
|
|
@@ -340,7 +340,7 @@ class MemoryBuilder(LoggerMixin):
|
|
|
340
340
|
Dict containing update results
|
|
341
341
|
"""
|
|
342
342
|
try:
|
|
343
|
-
from claude_mpm.services.
|
|
343
|
+
from claude_mpm.services.agents.memory import get_memory_manager
|
|
344
344
|
memory_manager = get_memory_manager(self.config)
|
|
345
345
|
|
|
346
346
|
result = {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Cache services for Claude MPM memory system.
|
|
2
|
+
|
|
3
|
+
This module provides caching services including:
|
|
4
|
+
- Simple in-memory caching with TTL support
|
|
5
|
+
- Shared prompt caching for agent prompts
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .simple_cache import SimpleCacheService
|
|
9
|
+
from .shared_prompt_cache import SharedPromptCache
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"SimpleCacheService",
|
|
13
|
+
"SharedPromptCache",
|
|
14
|
+
]
|
|
@@ -51,7 +51,7 @@ from pathlib import Path
|
|
|
51
51
|
from threading import RLock
|
|
52
52
|
from typing import Any, Dict, List, Optional, Set, Tuple, Union
|
|
53
53
|
|
|
54
|
-
from
|
|
54
|
+
from claude_mpm.core.base_service import BaseService, ServiceHealth, ServiceMetrics
|
|
55
55
|
|
|
56
56
|
|
|
57
57
|
@dataclass
|