claude-mpm 3.4.26__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 +6 -10
- 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.26.dist-info → claude_mpm-3.5.0.dist-info}/METADATA +26 -20
- {claude_mpm-3.4.26.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.26.dist-info → claude_mpm-3.5.0.dist-info}/WHEEL +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-3.4.26.dist-info → claude_mpm-3.5.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Response Tracker Service
|
|
3
|
+
|
|
4
|
+
Wraps the ClaudeSessionLogger to provide compatibility with the hook_handler.py
|
|
5
|
+
response tracking integration. This service acts as a bridge between the hook
|
|
6
|
+
system and the session logging system.
|
|
7
|
+
|
|
8
|
+
WHY: The hook_handler expects a ResponseTracker class with specific methods,
|
|
9
|
+
but we already have ClaudeSessionLogger that does the actual work. This wrapper
|
|
10
|
+
ensures compatibility while respecting configuration settings.
|
|
11
|
+
|
|
12
|
+
DESIGN DECISIONS:
|
|
13
|
+
- Wraps ClaudeSessionLogger instead of duplicating code
|
|
14
|
+
- Properly checks configuration to respect enabled/disabled state
|
|
15
|
+
- Provides the expected interface for hook_handler.py
|
|
16
|
+
- Handles agent name normalization for consistent tracking
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Dict, Any, Optional
|
|
22
|
+
from datetime import datetime
|
|
23
|
+
|
|
24
|
+
from claude_mpm.services.claude_session_logger import ClaudeSessionLogger
|
|
25
|
+
from claude_mpm.core.config import Config
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class ResponseTracker:
|
|
31
|
+
"""Response tracker that wraps ClaudeSessionLogger for hook compatibility.
|
|
32
|
+
|
|
33
|
+
WHY: This class provides the interface expected by hook_handler.py while
|
|
34
|
+
delegating actual logging to the proven ClaudeSessionLogger implementation.
|
|
35
|
+
This avoids code duplication and maintains consistency.
|
|
36
|
+
|
|
37
|
+
DESIGN: The tracker checks configuration settings on initialization and
|
|
38
|
+
respects the enabled/disabled state. It provides the track_response method
|
|
39
|
+
expected by the hook handler.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(self, config: Optional[Config] = None):
|
|
43
|
+
"""Initialize the response tracker.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
config: Optional configuration instance
|
|
47
|
+
"""
|
|
48
|
+
# Load configuration if not provided
|
|
49
|
+
if config is None:
|
|
50
|
+
config = Config()
|
|
51
|
+
self.config = config
|
|
52
|
+
|
|
53
|
+
# Check if response tracking is enabled
|
|
54
|
+
response_tracking_config = self.config.get('response_tracking', {})
|
|
55
|
+
response_logging_config = self.config.get('response_logging', {})
|
|
56
|
+
|
|
57
|
+
# Check both configurations - explicit False takes precedence
|
|
58
|
+
if 'enabled' in response_tracking_config:
|
|
59
|
+
self.enabled = response_tracking_config.get('enabled', False)
|
|
60
|
+
elif 'enabled' in response_logging_config:
|
|
61
|
+
self.enabled = response_logging_config.get('enabled', False)
|
|
62
|
+
else:
|
|
63
|
+
self.enabled = False # Default to disabled if not configured
|
|
64
|
+
|
|
65
|
+
# Initialize the session logger only if enabled
|
|
66
|
+
self.session_logger = None
|
|
67
|
+
if self.enabled:
|
|
68
|
+
try:
|
|
69
|
+
# Get base directory from configuration
|
|
70
|
+
base_dir = response_tracking_config.get('base_dir')
|
|
71
|
+
if not base_dir:
|
|
72
|
+
base_dir = response_logging_config.get('session_directory', '.claude-mpm/responses')
|
|
73
|
+
|
|
74
|
+
# Create session logger with proper configuration
|
|
75
|
+
self.session_logger = ClaudeSessionLogger(
|
|
76
|
+
base_dir=Path(base_dir),
|
|
77
|
+
config=config
|
|
78
|
+
)
|
|
79
|
+
logger.info(f"Response tracker initialized with base directory: {base_dir}")
|
|
80
|
+
except Exception as e:
|
|
81
|
+
logger.error(f"Failed to initialize session logger: {e}")
|
|
82
|
+
self.enabled = False
|
|
83
|
+
else:
|
|
84
|
+
logger.info("Response tracking is disabled in configuration")
|
|
85
|
+
|
|
86
|
+
def track_response(
|
|
87
|
+
self,
|
|
88
|
+
agent_name: str,
|
|
89
|
+
request: str,
|
|
90
|
+
response: str,
|
|
91
|
+
session_id: Optional[str] = None,
|
|
92
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
93
|
+
) -> Optional[Path]:
|
|
94
|
+
"""Track an agent response.
|
|
95
|
+
|
|
96
|
+
WHY: This method provides the interface expected by hook_handler.py
|
|
97
|
+
while delegating to ClaudeSessionLogger for actual storage.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
agent_name: Name of the agent that generated the response
|
|
101
|
+
request: The original request/prompt
|
|
102
|
+
response: The agent's response
|
|
103
|
+
session_id: Optional session ID (will use logger's if not provided)
|
|
104
|
+
metadata: Optional additional metadata
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Path to the saved response file, or None if disabled/failed
|
|
108
|
+
"""
|
|
109
|
+
# Check if tracking is enabled
|
|
110
|
+
if not self.enabled or not self.session_logger:
|
|
111
|
+
logger.debug(f"Response tracking disabled, skipping response from {agent_name}")
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
# Check excluded agents
|
|
115
|
+
response_tracking_config = self.config.get('response_tracking', {})
|
|
116
|
+
excluded_agents = response_tracking_config.get('excluded_agents', [])
|
|
117
|
+
|
|
118
|
+
# Normalize agent name for comparison
|
|
119
|
+
normalized_agent = agent_name.lower().replace('-', '_').replace(' ', '_')
|
|
120
|
+
|
|
121
|
+
# Check if agent is excluded
|
|
122
|
+
for excluded in excluded_agents:
|
|
123
|
+
excluded_normalized = excluded.lower().replace('-', '_').replace(' ', '_')
|
|
124
|
+
if normalized_agent == excluded_normalized:
|
|
125
|
+
logger.debug(f"Agent {agent_name} is in excluded list, skipping response tracking")
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
# Set session ID if provided
|
|
129
|
+
if session_id and session_id != self.session_logger.session_id:
|
|
130
|
+
self.session_logger.set_session_id(session_id)
|
|
131
|
+
|
|
132
|
+
# Prepare enhanced metadata
|
|
133
|
+
enhanced_metadata = metadata or {}
|
|
134
|
+
enhanced_metadata.update({
|
|
135
|
+
'agent': agent_name,
|
|
136
|
+
'tracked_by': 'ResponseTracker',
|
|
137
|
+
'tracking_timestamp': datetime.now().isoformat()
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
# Check if metadata tracking is enabled and add additional fields
|
|
141
|
+
metadata_tracking = response_tracking_config.get('metadata_tracking', {})
|
|
142
|
+
if metadata_tracking.get('track_model', True):
|
|
143
|
+
enhanced_metadata['model'] = enhanced_metadata.get('model', 'claude-3')
|
|
144
|
+
if metadata_tracking.get('track_duration', True) and 'duration_ms' in enhanced_metadata:
|
|
145
|
+
enhanced_metadata['duration_ms'] = enhanced_metadata.get('duration_ms')
|
|
146
|
+
if metadata_tracking.get('track_tools', True) and 'tool_name' in enhanced_metadata:
|
|
147
|
+
enhanced_metadata['tools_used'] = [enhanced_metadata.get('tool_name')]
|
|
148
|
+
|
|
149
|
+
# Log the response using the session logger
|
|
150
|
+
try:
|
|
151
|
+
file_path = self.session_logger.log_response(
|
|
152
|
+
request_summary=request,
|
|
153
|
+
response_content=response,
|
|
154
|
+
metadata=enhanced_metadata,
|
|
155
|
+
agent=agent_name
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if file_path:
|
|
159
|
+
logger.debug(f"Successfully tracked response from {agent_name} to {file_path}")
|
|
160
|
+
else:
|
|
161
|
+
logger.warning(f"Failed to track response from {agent_name}")
|
|
162
|
+
|
|
163
|
+
return file_path
|
|
164
|
+
|
|
165
|
+
except Exception as e:
|
|
166
|
+
logger.error(f"Error tracking response from {agent_name}: {e}")
|
|
167
|
+
return None
|
|
168
|
+
|
|
169
|
+
def is_enabled(self) -> bool:
|
|
170
|
+
"""Check if response tracking is enabled.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
True if tracking is enabled, False otherwise
|
|
174
|
+
"""
|
|
175
|
+
return self.enabled and self.session_logger is not None
|
|
176
|
+
|
|
177
|
+
def get_session_path(self) -> Optional[Path]:
|
|
178
|
+
"""Get the current session directory path.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
Path to the session directory, or None if not available
|
|
182
|
+
"""
|
|
183
|
+
if self.session_logger:
|
|
184
|
+
return self.session_logger.get_session_path()
|
|
185
|
+
return None
|
|
186
|
+
|
|
187
|
+
def set_session_id(self, session_id: str) -> None:
|
|
188
|
+
"""Set a specific session ID for tracking.
|
|
189
|
+
|
|
190
|
+
Args:
|
|
191
|
+
session_id: The session ID to use
|
|
192
|
+
"""
|
|
193
|
+
if self.session_logger:
|
|
194
|
+
self.session_logger.set_session_id(session_id)
|
|
195
|
+
logger.info(f"Response tracker session ID set to: {session_id}")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
# Singleton instance for consistency
|
|
199
|
+
_tracker_instance = None
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def get_response_tracker(config: Optional[Config] = None) -> ResponseTracker:
|
|
203
|
+
"""Get the singleton response tracker instance.
|
|
204
|
+
|
|
205
|
+
Args:
|
|
206
|
+
config: Optional configuration instance
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
The shared ResponseTracker instance
|
|
210
|
+
"""
|
|
211
|
+
global _tracker_instance
|
|
212
|
+
if _tracker_instance is None:
|
|
213
|
+
_tracker_instance = ResponseTracker(config=config)
|
|
214
|
+
return _tracker_instance
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def track_response(
|
|
218
|
+
agent_name: str,
|
|
219
|
+
request: str,
|
|
220
|
+
response: str,
|
|
221
|
+
session_id: Optional[str] = None,
|
|
222
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
223
|
+
) -> Optional[Path]:
|
|
224
|
+
"""Convenience function to track a response.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
agent_name: Name of the agent
|
|
228
|
+
request: The original request
|
|
229
|
+
response: The agent's response
|
|
230
|
+
session_id: Optional session ID
|
|
231
|
+
metadata: Optional metadata
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Path to the saved response file
|
|
235
|
+
"""
|
|
236
|
+
tracker = get_response_tracker()
|
|
237
|
+
return tracker.track_response(agent_name, request, response, session_id, metadata)
|
|
@@ -44,6 +44,8 @@ from datetime import datetime
|
|
|
44
44
|
from pathlib import Path
|
|
45
45
|
from typing import Any, Dict, List, Optional, Union
|
|
46
46
|
|
|
47
|
+
from claude_mpm.core.config_paths import ConfigPaths
|
|
48
|
+
|
|
47
49
|
# Import ai-trackdown-pytools
|
|
48
50
|
try:
|
|
49
51
|
from ai_trackdown_pytools import Task, Project
|
|
@@ -147,8 +149,8 @@ class TicketingService:
|
|
|
147
149
|
if tickets_path.exists():
|
|
148
150
|
return tickets_path
|
|
149
151
|
|
|
150
|
-
# Check for .claude-
|
|
151
|
-
claude_pm_dir = current_dir /
|
|
152
|
+
# Check for .claude-mpm directory
|
|
153
|
+
claude_pm_dir = current_dir / ConfigPaths.CONFIG_DIR
|
|
152
154
|
if claude_pm_dir.exists():
|
|
153
155
|
tickets_path = claude_pm_dir / "tickets"
|
|
154
156
|
tickets_path.mkdir(exist_ok=True)
|
|
@@ -17,6 +17,8 @@ from dataclasses import dataclass, field
|
|
|
17
17
|
import logging
|
|
18
18
|
import re
|
|
19
19
|
|
|
20
|
+
from claude_mpm.core.config_paths import ConfigPaths
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
class BranchStrategyType(Enum):
|
|
22
24
|
"""Types of branch strategies."""
|
|
@@ -303,7 +305,7 @@ class BranchStrategyManager:
|
|
|
303
305
|
"""Load strategy configuration from project files."""
|
|
304
306
|
# Try to load from configuration files
|
|
305
307
|
config_files = [
|
|
306
|
-
".
|
|
308
|
+
f"{ConfigPaths.CONFIG_DIR}/config.json",
|
|
307
309
|
"workflow.md",
|
|
308
310
|
".github/workflows/branch-strategy.yml",
|
|
309
311
|
"branch-strategy.json",
|
claude_mpm/utils/paths.py
CHANGED
|
@@ -10,6 +10,8 @@ from typing import Optional, Union, List
|
|
|
10
10
|
from functools import lru_cache
|
|
11
11
|
import logging
|
|
12
12
|
|
|
13
|
+
from claude_mpm.core.config_paths import ConfigPaths
|
|
14
|
+
|
|
13
15
|
logger = logging.getLogger(__name__)
|
|
14
16
|
|
|
15
17
|
|
|
@@ -109,7 +111,7 @@ class PathResolver:
|
|
|
109
111
|
"""
|
|
110
112
|
# Project root markers in order of preference
|
|
111
113
|
markers = ['.git', 'pyproject.toml', 'package.json', 'Cargo.toml',
|
|
112
|
-
'go.mod', 'pom.xml', 'build.gradle',
|
|
114
|
+
'go.mod', 'pom.xml', 'build.gradle', ConfigPaths.CONFIG_DIR]
|
|
113
115
|
|
|
114
116
|
current = Path.cwd()
|
|
115
117
|
while current != current.parent:
|
|
@@ -139,22 +141,22 @@ class PathResolver:
|
|
|
139
141
|
FileNotFoundError: If directory cannot be determined
|
|
140
142
|
"""
|
|
141
143
|
if scope == 'project':
|
|
142
|
-
return cls.get_project_root() /
|
|
144
|
+
return cls.get_project_root() / ConfigPaths.CONFIG_DIR
|
|
143
145
|
elif scope == 'user':
|
|
144
146
|
# Support XDG_CONFIG_HOME if set
|
|
145
147
|
xdg_config = os.environ.get('XDG_CONFIG_HOME')
|
|
146
148
|
if xdg_config:
|
|
147
|
-
return Path(xdg_config) / 'claude-
|
|
148
|
-
return Path.home() / '.config' / 'claude-
|
|
149
|
+
return Path(xdg_config) / 'claude-mpm'
|
|
150
|
+
return Path.home() / '.config' / 'claude-mpm'
|
|
149
151
|
elif scope == 'system':
|
|
150
152
|
# System-wide configuration
|
|
151
153
|
if os.name == 'posix':
|
|
152
|
-
return Path('/etc/claude-
|
|
154
|
+
return Path('/etc/claude-mpm')
|
|
153
155
|
else:
|
|
154
156
|
# Windows: Use ProgramData
|
|
155
|
-
return Path(os.environ.get('ProgramData', 'C:\\ProgramData')) / 'claude-
|
|
157
|
+
return Path(os.environ.get('ProgramData', 'C:\\ProgramData')) / 'claude-mpm'
|
|
156
158
|
elif scope == 'framework':
|
|
157
|
-
return cls.get_framework_root() /
|
|
159
|
+
return cls.get_framework_root() / ConfigPaths.CONFIG_DIR
|
|
158
160
|
else:
|
|
159
161
|
raise ValueError(f"Invalid scope: {scope}. Must be one of: project, user, system, framework")
|
|
160
162
|
|
|
@@ -186,15 +188,15 @@ class PathResolver:
|
|
|
186
188
|
@classmethod
|
|
187
189
|
@lru_cache(maxsize=8)
|
|
188
190
|
def get_claude_pm_dir(cls, base_path: Optional[Path] = None) -> Optional[Path]:
|
|
189
|
-
"""Find .claude-
|
|
191
|
+
"""Find .claude-mpm directory starting from base_path.
|
|
190
192
|
|
|
191
193
|
Args:
|
|
192
194
|
base_path: Starting directory (defaults to current directory)
|
|
193
195
|
|
|
194
196
|
Returns:
|
|
195
|
-
Path: The .claude-
|
|
197
|
+
Path: The .claude-mpm directory, or None if not found
|
|
196
198
|
"""
|
|
197
|
-
result = cls.find_file_upwards(
|
|
199
|
+
result = cls.find_file_upwards(ConfigPaths.CONFIG_DIR, base_path)
|
|
198
200
|
return result if result and result.is_dir() else None
|
|
199
201
|
|
|
200
202
|
@classmethod
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Session Logging Utilities
|
|
3
|
+
|
|
4
|
+
Convenience functions for session-based response logging.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
from typing import Optional, Dict, Any
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
import logging
|
|
11
|
+
|
|
12
|
+
from claude_mpm.services.claude_session_logger import get_session_logger
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def is_session_logging_enabled() -> bool:
|
|
18
|
+
"""
|
|
19
|
+
Check if session logging is enabled.
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
True if session logging is enabled and configured
|
|
23
|
+
"""
|
|
24
|
+
# Check environment variable to disable
|
|
25
|
+
if os.environ.get('CLAUDE_MPM_NO_SESSION_LOGGING', '').lower() in ('1', 'true', 'yes'):
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
# Check if session logger has a valid session ID
|
|
29
|
+
session_logger = get_session_logger()
|
|
30
|
+
return session_logger.is_enabled()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def log_agent_response(
|
|
34
|
+
agent_name: str,
|
|
35
|
+
request: str,
|
|
36
|
+
response: str,
|
|
37
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
38
|
+
) -> Optional[Path]:
|
|
39
|
+
"""
|
|
40
|
+
Log an agent response to the current session.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
agent_name: Name of the agent
|
|
44
|
+
request: The request/prompt sent to the agent
|
|
45
|
+
response: The agent's response
|
|
46
|
+
metadata: Optional additional metadata
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Path to the logged file, or None if logging is disabled
|
|
50
|
+
"""
|
|
51
|
+
if not is_session_logging_enabled():
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
# Create request summary
|
|
55
|
+
request_summary = f"[{agent_name}] {request[:100]}..." if len(request) > 100 else f"[{agent_name}] {request}"
|
|
56
|
+
|
|
57
|
+
# Add agent name to metadata
|
|
58
|
+
if metadata is None:
|
|
59
|
+
metadata = {}
|
|
60
|
+
metadata['agent'] = agent_name
|
|
61
|
+
|
|
62
|
+
# Log the response
|
|
63
|
+
session_logger = get_session_logger()
|
|
64
|
+
return session_logger.log_response(
|
|
65
|
+
request_summary=request_summary,
|
|
66
|
+
response_content=response,
|
|
67
|
+
metadata=metadata
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def get_current_session_id() -> Optional[str]:
|
|
72
|
+
"""
|
|
73
|
+
Get the current session ID.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
Current session ID, or None if not available
|
|
77
|
+
"""
|
|
78
|
+
session_logger = get_session_logger()
|
|
79
|
+
return session_logger.session_id
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_session_directory() -> Optional[Path]:
|
|
83
|
+
"""
|
|
84
|
+
Get the directory for the current session.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
Path to session directory, or None if not available
|
|
88
|
+
"""
|
|
89
|
+
session_logger = get_session_logger()
|
|
90
|
+
return session_logger.get_session_path()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def set_session_id(session_id: str) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Manually set the session ID.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
session_id: The session ID to use
|
|
99
|
+
"""
|
|
100
|
+
session_logger = get_session_logger()
|
|
101
|
+
session_logger.set_session_id(session_id)
|
|
102
|
+
logger.info(f"Session ID set to: {session_id}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# Environment variable helpers
|
|
106
|
+
def enable_session_logging() -> None:
|
|
107
|
+
"""Enable session logging by removing disable flag."""
|
|
108
|
+
if 'CLAUDE_MPM_NO_SESSION_LOGGING' in os.environ:
|
|
109
|
+
del os.environ['CLAUDE_MPM_NO_SESSION_LOGGING']
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def disable_session_logging() -> None:
|
|
113
|
+
"""Disable session logging via environment variable."""
|
|
114
|
+
os.environ['CLAUDE_MPM_NO_SESSION_LOGGING'] = '1'
|
|
@@ -27,6 +27,7 @@ from dataclasses import dataclass, field
|
|
|
27
27
|
from datetime import datetime
|
|
28
28
|
import jsonschema
|
|
29
29
|
from jsonschema import validate, ValidationError, Draft7Validator
|
|
30
|
+
from claude_mpm.config.paths import paths
|
|
30
31
|
|
|
31
32
|
logger = logging.getLogger(__name__)
|
|
32
33
|
|
|
@@ -55,7 +56,7 @@ class AgentValidator:
|
|
|
55
56
|
def __init__(self, schema_path: Optional[Path] = None):
|
|
56
57
|
"""Initialize the validator with the agent schema."""
|
|
57
58
|
if schema_path is None:
|
|
58
|
-
schema_path =
|
|
59
|
+
schema_path = paths.schemas_dir / "agent_schema.json"
|
|
59
60
|
|
|
60
61
|
self.schema_path = schema_path
|
|
61
62
|
self.schema = self._load_schema()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-mpm
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.5.0
|
|
4
4
|
Summary: Claude Multi-agent Project Manager - Clean orchestration with ticket management
|
|
5
5
|
Home-page: https://github.com/bobmatnyc/claude-mpm
|
|
6
6
|
Author: Claude MPM Team
|
|
@@ -22,7 +22,6 @@ License-File: LICENSE
|
|
|
22
22
|
Requires-Dist: ai-trackdown-pytools>=1.4.0
|
|
23
23
|
Requires-Dist: pyyaml>=6.0
|
|
24
24
|
Requires-Dist: python-dotenv>=0.19.0
|
|
25
|
-
Requires-Dist: rich>=13.0.0
|
|
26
25
|
Requires-Dist: click>=8.0.0
|
|
27
26
|
Requires-Dist: pexpect>=4.8.0
|
|
28
27
|
Requires-Dist: psutil>=5.9.0
|
|
@@ -36,7 +35,6 @@ Requires-Dist: python-socketio>=5.11.0
|
|
|
36
35
|
Requires-Dist: aiohttp>=3.9.0
|
|
37
36
|
Requires-Dist: aiohttp-cors>=0.8.0
|
|
38
37
|
Requires-Dist: python-engineio>=4.8.0
|
|
39
|
-
Requires-Dist: urwid>=2.1.0
|
|
40
38
|
Provides-Extra: dev
|
|
41
39
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
42
40
|
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
@@ -58,7 +56,7 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
|
|
|
58
56
|
|
|
59
57
|
## Features
|
|
60
58
|
|
|
61
|
-
- 🤖 **Multi-Agent System**: Automatically delegates tasks to specialized agents (PM, Research, Engineer, QA, Documentation, Security, Ops, Data Engineer)
|
|
59
|
+
- 🤖 **Multi-Agent System**: Automatically delegates tasks to specialized agents (PM, Research, Engineer, QA, Documentation, Security, Ops, Data Engineer, Test Integration, Version Control)
|
|
62
60
|
- 🧠 **Agent Memory System**: Persistent learning with project-specific knowledge retention
|
|
63
61
|
- 🔄 **Session Management**: Resume previous sessions with `--resume`
|
|
64
62
|
- 📊 **Real-Time Monitoring**: Live dashboard with `--monitor` flag
|
|
@@ -72,8 +70,8 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
|
|
|
72
70
|
# Install from PyPI
|
|
73
71
|
pip install claude-mpm
|
|
74
72
|
|
|
75
|
-
#
|
|
76
|
-
pip install "claude-mpm[
|
|
73
|
+
# Install with development dependencies
|
|
74
|
+
pip install "claude-mpm[dev]"
|
|
77
75
|
```
|
|
78
76
|
|
|
79
77
|
## Basic Usage
|
|
@@ -104,6 +102,9 @@ The PM agent automatically delegates work to specialized agents:
|
|
|
104
102
|
- **Documentation**: Docs and guides
|
|
105
103
|
- **Security**: Security analysis
|
|
106
104
|
- **Ops**: Deployment and infrastructure
|
|
105
|
+
- **Data Engineer**: Data pipelines and AI integrations
|
|
106
|
+
- **Test Integration**: E2E testing and cross-system validation
|
|
107
|
+
- **Version Control**: Git workflows and release management
|
|
107
108
|
|
|
108
109
|
### Session Management
|
|
109
110
|
- All work is tracked in persistent sessions
|
|
@@ -127,6 +128,9 @@ claude-mpm memory status
|
|
|
127
128
|
|
|
128
129
|
# Add specific learning
|
|
129
130
|
claude-mpm memory add engineer pattern "Always use async/await for I/O"
|
|
131
|
+
|
|
132
|
+
# Start with monitoring dashboard
|
|
133
|
+
claude-mpm run --monitor
|
|
130
134
|
```
|
|
131
135
|
|
|
132
136
|
See [docs/MEMORY.md](docs/MEMORY.md) for comprehensive memory system documentation.
|
|
@@ -138,39 +142,41 @@ The `--monitor` flag opens a web dashboard showing:
|
|
|
138
142
|
- Tool usage and results
|
|
139
143
|
- Session management UI
|
|
140
144
|
|
|
141
|
-
See [docs/monitoring.md](docs/monitoring.md) for full monitoring guide.
|
|
145
|
+
See [docs/developer/monitoring.md](docs/developer/monitoring.md) for full monitoring guide.
|
|
142
146
|
|
|
143
147
|
|
|
144
148
|
## Documentation
|
|
145
149
|
|
|
146
150
|
- **[Quick Start Guide](QUICKSTART.md)** - Get running in 5 minutes
|
|
147
151
|
- **[Agent Memory System](docs/MEMORY.md)** - Comprehensive memory documentation
|
|
148
|
-
- **[Monitoring Dashboard](docs/monitoring.md)** - Real-time monitoring features
|
|
152
|
+
- **[Monitoring Dashboard](docs/developer/monitoring.md)** - Real-time monitoring features
|
|
149
153
|
- **[Project Structure](docs/STRUCTURE.md)** - Codebase organization
|
|
150
154
|
- **[Deployment Guide](docs/DEPLOY.md)** - Publishing and versioning
|
|
151
155
|
- **[User Guide](docs/user/)** - Detailed usage documentation
|
|
152
156
|
- **[Developer Guide](docs/developer/)** - Architecture and API reference
|
|
153
157
|
|
|
154
|
-
## Recent Updates (v3.4.
|
|
158
|
+
## Recent Updates (v3.4.27)
|
|
155
159
|
|
|
156
|
-
###
|
|
157
|
-
- **Project
|
|
158
|
-
- **
|
|
159
|
-
- **
|
|
160
|
-
- **
|
|
160
|
+
### Core System Enhancements
|
|
161
|
+
- **Project Structure Reorganization**: Centralized path management with ClaudeMPMPaths enum
|
|
162
|
+
- **Agent Services Hierarchy**: Reorganized agent and memory services into hierarchical structures
|
|
163
|
+
- **Response Logging Improvements**: Flat structure logging without session_ prefix
|
|
164
|
+
- **Memory System Expansion**: Added data_engineer and test_integration agents with specialized keywords
|
|
165
|
+
- **Path Management System**: Implemented centralized configuration path handling
|
|
161
166
|
|
|
162
|
-
### Project Organization
|
|
163
|
-
- **
|
|
164
|
-
- **Documentation Archives**:
|
|
165
|
-
- **
|
|
166
|
-
- **
|
|
167
|
+
### Project Cleanup & Organization
|
|
168
|
+
- **Test File Migration**: Moved 66 test files from scripts/ to tests/ directory
|
|
169
|
+
- **Documentation Archives**: Archived 35+ QA reports to docs/archive/
|
|
170
|
+
- **Obsolete Directory Removal**: Cleaned up orchestration, docker, security, and terminal_wrapper directories
|
|
171
|
+
- **Agent Registry Caching**: Enhanced performance with intelligent caching mechanisms
|
|
172
|
+
- **Improved TodoWrite Integration**: Enhanced agent prefix guidelines across all agent templates
|
|
167
173
|
|
|
168
174
|
See [CHANGELOG.md](CHANGELOG.md) for full history.
|
|
169
175
|
|
|
170
176
|
## Development
|
|
171
177
|
|
|
172
178
|
### Contributing
|
|
173
|
-
|
|
179
|
+
Contributions are welcome! Please see our [project structure guide](docs/STRUCTURE.md) and follow the established patterns.
|
|
174
180
|
|
|
175
181
|
### Project Structure
|
|
176
182
|
See [docs/STRUCTURE.md](docs/STRUCTURE.md) for codebase organization.
|