claude-mpm 2.0.0__py3-none-any.whl → 2.1.1__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.
@@ -0,0 +1,227 @@
1
+ """Deployed Agent Discovery Service.
2
+
3
+ This service discovers and analyzes deployed agents in the project,
4
+ handling both new standardized schema and legacy agent formats.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import List, Dict, Any
9
+ import logging
10
+ import json
11
+
12
+ from claude_mpm.core.agent_registry import AgentRegistryAdapter
13
+ from claude_mpm.utils.paths import PathResolver
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ class DeployedAgentDiscovery:
19
+ """Discovers and analyzes deployed agents in the project."""
20
+
21
+ def __init__(self, project_root: Path = None):
22
+ """Initialize the discovery service.
23
+
24
+ Args:
25
+ project_root: Project root path. Defaults to auto-detected root.
26
+ """
27
+ self.project_root = project_root or PathResolver.get_project_root()
28
+ self.agent_registry = AgentRegistryAdapter()
29
+ logger.debug(f"Initialized DeployedAgentDiscovery with root: {self.project_root}")
30
+
31
+ def discover_deployed_agents(self) -> List[Dict[str, Any]]:
32
+ """Discover all deployed agents following hierarchy precedence.
33
+
34
+ Returns:
35
+ List of agent information dictionaries with standardized fields.
36
+ """
37
+ try:
38
+ # Get effective agents (respects project > user > system precedence)
39
+ agents = self.agent_registry.list_agents()
40
+
41
+ # Handle both dict and list formats
42
+ if isinstance(agents, dict):
43
+ agent_list = list(agents.values())
44
+ else:
45
+ agent_list = list(agents)
46
+
47
+ logger.debug(f"Found {len(agent_list)} entries in registry")
48
+
49
+ deployed_agents = []
50
+ filtered_count = 0
51
+ for agent in agent_list:
52
+ try:
53
+ agent_info = self._extract_agent_info(agent)
54
+ if agent_info and self._is_valid_agent(agent_info):
55
+ deployed_agents.append(agent_info)
56
+ logger.debug(f"Extracted info for agent: {agent_info['id']}")
57
+ elif agent_info:
58
+ filtered_count += 1
59
+ logger.debug(f"Filtered out non-deployable agent: {agent_info.get('id', 'unknown')}")
60
+ except Exception as e:
61
+ logger.error(f"Failed to extract info from agent {agent}: {e}")
62
+ continue
63
+
64
+ logger.info(f"Discovered {len(deployed_agents)} deployable agents from registry ({filtered_count} templates/base agents filtered out)")
65
+ return deployed_agents
66
+
67
+ except Exception as e:
68
+ logger.error(f"Failed to discover deployed agents: {e}")
69
+ # Return empty list on failure to allow graceful degradation
70
+ return []
71
+
72
+ def _extract_agent_info(self, agent) -> Dict[str, Any]:
73
+ """Extract relevant information from agent definition.
74
+
75
+ Args:
76
+ agent: Agent object from registry (can be dict or object)
77
+
78
+ Returns:
79
+ Dictionary with standardized agent information
80
+ """
81
+ try:
82
+ # Handle dictionary format (current format from registry)
83
+ if isinstance(agent, dict):
84
+ # If we have a path, try to load full agent data from JSON
85
+ agent_path = agent.get('path')
86
+ if agent_path and agent_path.endswith('.json'):
87
+ full_data = self._load_full_agent_data(agent_path)
88
+ if full_data:
89
+ return self._extract_from_json_data(full_data, agent)
90
+
91
+ # Otherwise use basic info from registry
92
+ return {
93
+ 'id': agent.get('type', agent.get('name', 'unknown')),
94
+ 'name': agent.get('name', 'Unknown'),
95
+ 'description': agent.get('description', 'No description available'),
96
+ 'specializations': agent.get('specializations', []),
97
+ 'capabilities': agent.get('capabilities', {}),
98
+ 'source_tier': agent.get('tier', 'system'),
99
+ 'tools': agent.get('tools', [])
100
+ }
101
+ # Handle object format with metadata (new standardized schema)
102
+ elif hasattr(agent, 'metadata'):
103
+ return {
104
+ 'id': agent.agent_id,
105
+ 'name': agent.metadata.name,
106
+ 'description': agent.metadata.description,
107
+ 'specializations': agent.metadata.specializations,
108
+ 'capabilities': getattr(agent, 'capabilities', {}),
109
+ 'source_tier': self._determine_source_tier(agent),
110
+ 'tools': getattr(agent.configuration, 'tools', []) if hasattr(agent, 'configuration') else []
111
+ }
112
+ else:
113
+ # Legacy object format fallback
114
+ agent_type = getattr(agent, 'type', None)
115
+ agent_name = getattr(agent, 'name', None)
116
+
117
+ # Generate name from type if name not present
118
+ if not agent_name and agent_type:
119
+ agent_name = agent_type.replace('_', ' ').title()
120
+ elif not agent_name:
121
+ agent_name = 'Unknown Agent'
122
+
123
+ return {
124
+ 'id': getattr(agent, 'agent_id', agent_type or 'unknown'),
125
+ 'name': agent_name,
126
+ 'description': getattr(agent, 'description', 'No description available'),
127
+ 'specializations': getattr(agent, 'specializations', []),
128
+ 'capabilities': {},
129
+ 'source_tier': self._determine_source_tier(agent),
130
+ 'tools': getattr(agent, 'tools', [])
131
+ }
132
+ except Exception as e:
133
+ logger.error(f"Error extracting agent info: {e}")
134
+ return None
135
+
136
+ def _load_full_agent_data(self, agent_path: str) -> Dict[str, Any]:
137
+ """Load full agent data from JSON file.
138
+
139
+ Args:
140
+ agent_path: Path to agent JSON file
141
+
142
+ Returns:
143
+ Full agent data dictionary or None if loading fails
144
+ """
145
+ try:
146
+ path = Path(agent_path)
147
+ if path.exists() and path.suffix == '.json':
148
+ with open(path, 'r') as f:
149
+ return json.load(f)
150
+ except Exception as e:
151
+ logger.warning(f"Failed to load full agent data from {agent_path}: {e}")
152
+ return None
153
+
154
+ def _extract_from_json_data(self, json_data: Dict[str, Any], registry_info: Dict[str, Any]) -> Dict[str, Any]:
155
+ """Extract agent info from full JSON data.
156
+
157
+ Args:
158
+ json_data: Full agent JSON data
159
+ registry_info: Basic info from registry
160
+
161
+ Returns:
162
+ Extracted agent information
163
+ """
164
+ # Extract metadata
165
+ metadata = json_data.get('metadata', {})
166
+ capabilities = json_data.get('capabilities', {})
167
+ configuration = json_data.get('configuration', {})
168
+
169
+ return {
170
+ 'id': json_data.get('agent_type', registry_info.get('type', 'unknown')),
171
+ 'name': metadata.get('name', registry_info.get('name', 'Unknown')),
172
+ 'description': metadata.get('description', registry_info.get('description', 'No description available')),
173
+ 'specializations': metadata.get('specializations', registry_info.get('specializations', [])),
174
+ 'capabilities': capabilities,
175
+ 'source_tier': registry_info.get('tier', 'system'),
176
+ 'tools': configuration.get('tools', [])
177
+ }
178
+
179
+ def _determine_source_tier(self, agent) -> str:
180
+ """Determine if agent comes from project, user, or system tier.
181
+
182
+ Args:
183
+ agent: Agent object from registry (can be dict or object)
184
+
185
+ Returns:
186
+ Source tier string: 'project', 'user', or 'system'
187
+ """
188
+ # Handle dictionary format
189
+ if isinstance(agent, dict):
190
+ return agent.get('tier', 'system')
191
+
192
+ # First check if agent has explicit source_tier attribute
193
+ if hasattr(agent, 'source_tier'):
194
+ return agent.source_tier
195
+
196
+ # Try to determine from file path if available
197
+ if hasattr(agent, 'source_path'):
198
+ source_path = str(agent.source_path)
199
+ if '.claude/agents' in source_path:
200
+ return 'project'
201
+ elif str(Path.home()) in source_path:
202
+ return 'user'
203
+
204
+ # Default to system tier
205
+ return 'system'
206
+
207
+ def _is_valid_agent(self, agent_info: Dict[str, Any]) -> bool:
208
+ """Check if agent is a valid deployable agent (not a template).
209
+
210
+ Args:
211
+ agent_info: Extracted agent information
212
+
213
+ Returns:
214
+ True if agent is valid, False if it's a template or invalid
215
+ """
216
+ # Filter out known templates and non-agent files
217
+ invalid_names = ['BASE_AGENT_TEMPLATE', 'INSTRUCTIONS', 'base_agent', 'template']
218
+
219
+ agent_id = agent_info.get('id', '').upper()
220
+ agent_name = agent_info.get('name', '').upper()
221
+
222
+ for invalid in invalid_names:
223
+ if invalid.upper() in agent_id or invalid.upper() in agent_name:
224
+ logger.debug(f"Filtering out template/invalid agent: {agent_info['id']}")
225
+ return False
226
+
227
+ return True
@@ -8,6 +8,12 @@ import hashlib
8
8
  from datetime import datetime
9
9
  from typing import Dict, List, Optional, Any
10
10
  from collections import OrderedDict
11
+ import logging
12
+
13
+ from claude_mpm.services.deployed_agent_discovery import DeployedAgentDiscovery
14
+ from claude_mpm.services.agent_capabilities_generator import AgentCapabilitiesGenerator
15
+
16
+ logger = logging.getLogger(__name__)
11
17
 
12
18
 
13
19
  class ContentAssembler:
@@ -16,6 +22,9 @@ class ContentAssembler:
16
22
  def __init__(self):
17
23
  """Initialize content assembler."""
18
24
  self.template_variables = {}
25
+ self.agent_discovery = DeployedAgentDiscovery()
26
+ self.capabilities_generator = AgentCapabilitiesGenerator()
27
+ logger.debug("Initialized ContentAssembler with dynamic agent capabilities support")
19
28
 
20
29
  def generate_content_hash(self) -> str:
21
30
  """
@@ -63,12 +72,32 @@ class ContentAssembler:
63
72
  """
64
73
  Apply template variable substitution to content.
65
74
 
75
+ WHY: Enhanced to support dynamic agent capabilities generation.
76
+ - Generates fresh agent capabilities on each call
77
+ - Provides graceful fallback if generation fails
78
+ - Ensures INSTRUCTIONS.md always reflects current deployed agents
79
+
66
80
  Args:
67
81
  content: Content with template variables
68
82
 
69
83
  Returns:
70
84
  str: Content with variables substituted
71
85
  """
86
+ # Check if we need to generate dynamic capabilities
87
+ if "{{capabilities-list}}" in content:
88
+ try:
89
+ # Discover deployed agents
90
+ deployed_agents = self.agent_discovery.discover_deployed_agents()
91
+ # Generate capabilities content
92
+ capabilities_content = self.capabilities_generator.generate_capabilities_section(deployed_agents)
93
+ # Add to template variables
94
+ self.template_variables['capabilities-list'] = capabilities_content
95
+ logger.info(f"Generated dynamic capabilities for {len(deployed_agents)} agents")
96
+ except Exception as e:
97
+ logger.error(f"Failed to generate dynamic capabilities: {e}")
98
+ # Fallback is handled by the generator's internal fallback mechanism
99
+
100
+ # Apply all template variables
72
101
  for var_name, var_value in self.template_variables.items():
73
102
  placeholder = f"{{{{{var_name}}}}}"
74
103
  content = content.replace(placeholder, var_value)
@@ -35,6 +35,11 @@ class DeploymentManager:
35
35
  """
36
36
  Deploy generated content to a parent directory.
37
37
 
38
+ WHY: Enhanced to ensure fresh agent capabilities generation on each deployment.
39
+ - Checks for template variables that need processing
40
+ - Re-processes content to get current deployed agents
41
+ - Ensures INSTRUCTIONS.md always reflects latest agent configuration
42
+
38
43
  Args:
39
44
  content: Content to deploy
40
45
  parent_path: Path to parent directory
@@ -52,16 +57,33 @@ class DeploymentManager:
52
57
  target_file = parent_path / "INSTRUCTIONS.md"
53
58
  # TODO: Make this configurable via parameter
54
59
 
60
+ # Check if content contains template variables that need processing
61
+ if '{{capabilities-list}}' in content:
62
+ # Content needs processing - let ContentAssembler handle it
63
+ from .content_assembler import ContentAssembler
64
+ assembler = ContentAssembler()
65
+
66
+ # Re-process content to get fresh agent data
67
+ # Pass content as a single section to preserve structure
68
+ processed_content = assembler.apply_template_variables(content)
69
+ content = processed_content
70
+
55
71
  # Validate content before deployment
56
- is_valid, issues = self.validator.validate_content(content)
57
- if not is_valid:
58
- return False, f"Validation failed: {'; '.join(issues)}"
72
+ # Skip validation for INSTRUCTIONS.md format (different from CLAUDE.md)
73
+ if "<!-- FRAMEWORK_VERSION:" in content and "# Claude Multi-Agent Project Manager Instructions" in content:
74
+ # This is INSTRUCTIONS.md format, skip CLAUDE.md validation
75
+ pass
76
+ else:
77
+ # This is CLAUDE.md format, validate normally
78
+ is_valid, issues = self.validator.validate_content(content)
79
+ if not is_valid:
80
+ return False, f"Validation failed: {'; '.join(issues)}"
59
81
 
60
82
  # Check if file exists and compare versions
61
83
  if target_file.exists() and not force:
62
84
  with open(target_file, 'r') as f:
63
85
  existing_content = f.read()
64
- existing_fw_ver, _ = self.version_manager.parse_current_version(existing_content)
86
+ existing_fw_ver = self.version_manager.parse_current_version(existing_content)
65
87
 
66
88
  if existing_fw_ver == self.version_manager.framework_version:
67
89
  return True, f"Version {existing_fw_ver} already deployed"
@@ -76,8 +98,8 @@ class DeploymentManager:
76
98
  f.write(content)
77
99
 
78
100
  # Get version info for success message
79
- fw_ver, serial = self.version_manager.parse_current_version(content)
80
- version_str = f"{fw_ver}-{serial:03d}"
101
+ fw_ver = self.version_manager.parse_current_version(content)
102
+ version_str = fw_ver
81
103
 
82
104
  return True, f"Successfully deployed version {version_str}"
83
105
  except Exception as e:
@@ -101,7 +123,7 @@ class DeploymentManager:
101
123
  try:
102
124
  with open(target_file, 'r') as f:
103
125
  existing_content = f.read()
104
- existing_fw_ver, _ = self.version_manager.parse_current_version(existing_content)
126
+ existing_fw_ver = self.version_manager.parse_current_version(existing_content)
105
127
 
106
128
  if existing_fw_ver != self.version_manager.framework_version:
107
129
  return True, f"Version mismatch: {existing_fw_ver} vs {self.version_manager.framework_version}"
@@ -0,0 +1,39 @@
1
+ """Framework source directory detection utilities.
2
+
3
+ WHY: This module provides utilities to detect if we're in the framework source directory
4
+ to prevent accidental overwrites of the template files during deployment.
5
+ """
6
+
7
+ from pathlib import Path
8
+ from typing import Tuple, List
9
+
10
+
11
+ def is_framework_source_directory(path: Path) -> Tuple[bool, List[str]]:
12
+ """
13
+ Check if the given path is the framework source directory.
14
+
15
+ WHY: We need to prevent deployment to the framework source directory itself
16
+ to avoid overwriting template files.
17
+
18
+ Args:
19
+ path: Path to check
20
+
21
+ Returns:
22
+ Tuple of (is_framework_source, list of detected markers)
23
+ """
24
+ markers = []
25
+
26
+ # Check for framework source markers
27
+ if (path / "src" / "claude_mpm").exists():
28
+ markers.append("src/claude_mpm")
29
+
30
+ if (path / "pyproject.toml").exists():
31
+ markers.append("pyproject.toml")
32
+
33
+ if (path / "src" / "claude_mpm" / "agents" / "INSTRUCTIONS.md").exists():
34
+ markers.append("framework INSTRUCTIONS.md template")
35
+
36
+ # If we have multiple markers, it's likely the framework source
37
+ is_framework = len(markers) >= 2
38
+
39
+ return is_framework, markers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 2.0.0
3
+ Version: 2.1.1
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
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3.11
18
18
  Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.8
20
20
  Description-Content-Type: text/markdown
21
+ License-File: LICENSE
21
22
  Requires-Dist: ai-trackdown-pytools>=1.2.0
22
23
  Requires-Dist: pyyaml>=6.0
23
24
  Requires-Dist: python-dotenv>=0.19.0
@@ -40,6 +41,7 @@ Requires-Dist: flake8; extra == "dev"
40
41
  Requires-Dist: mypy; extra == "dev"
41
42
  Dynamic: author-email
42
43
  Dynamic: home-page
44
+ Dynamic: license-file
43
45
  Dynamic: requires-python
44
46
 
45
47
  # Claude MPM - Multi-Agent Project Manager
@@ -194,6 +196,7 @@ Claude MPM provides a modular framework for extending Claude's capabilities:
194
196
  - Dynamic agent discovery and registration
195
197
  - Template-based agent definitions
196
198
  - Extensible agent architecture
199
+ - **Dynamic Capabilities**: Agent documentation automatically generated from deployed agents
197
200
 
198
201
  ### Hook System
199
202
  - Pre and post-processing hooks
@@ -213,6 +216,13 @@ Claude MPM provides a modular framework for extending Claude's capabilities:
213
216
  - Organized log structure
214
217
  - Performance monitoring
215
218
 
219
+ ### Security Features
220
+ - **File System Protection**: Automatic sandboxing prevents file operations outside the working directory
221
+ - **Path Traversal Prevention**: Blocks attempts to escape the project directory using `..` or symlinks
222
+ - **Write Operation Control**: All write operations are validated while read operations remain unrestricted
223
+ - **Transparent Security**: Zero-configuration security that works automatically in the background
224
+ - **Comprehensive Logging**: All security events are logged for audit purposes
225
+
216
226
  ## Installation
217
227
 
218
228
  ### Other Installation Methods
@@ -1,13 +1,13 @@
1
1
  claude_mpm/__init__.py,sha256=sAbTZkHe3vWYAKDWdGyGVue5zwLD7nCOHZwZrLALM8A,395
2
2
  claude_mpm/__main__.py,sha256=smBw-5J3nf5s6GgQjj384GUr28YotIX-WNOxqpP0wnE,310
3
- claude_mpm/_version.py,sha256=Ng-R0tLTmF6GT0YoJek11nrB3KB8c3Q4YfYsQ_cKXvw,1394
4
- claude_mpm/cli.py,sha256=EgzmFR-6njXedJUtMrWY0o-QAezsY3fc8uObehDDPMw,23164
3
+ claude_mpm/_version.py,sha256=HBkjBFMyGB0Jyz0lTkWhWTEalldfBZqkqfHkyuIxBJk,159
4
+ claude_mpm/cli.py,sha256=_6tUSY0FqBN6cHR6awuXgqm2-Hlh-L508rB-RDgflPU,26036
5
5
  claude_mpm/cli_enhancements.py,sha256=nwdOrbXITRqvcq_vrJtPKW1GDS7dLIG4UqjoUet2vR0,10890
6
6
  claude_mpm/cli_main.py,sha256=KCAe-ws73NrIg5qmFhPdZ1a4uoiaEZ-lldYzQ6KfnJg,306
7
7
  claude_mpm/constants.py,sha256=5AG5hgBxOC7gMNHDx0lAhS-FQ8gXhtGtqJ9Moj3S6ro,4044
8
8
  claude_mpm/init.py,sha256=gOreOf7BLXkT0_HrQk_As4Kz1OT_NJG_RG0i0hbY0z0,8088
9
9
  claude_mpm/agents/BASE_AGENT_TEMPLATE.md,sha256=TYgSd9jNBMWp4mAOBUl9dconX4RcGbvmMEScRy5uyko,3343
10
- claude_mpm/agents/INSTRUCTIONS.md,sha256=I2Y_Aed6-E6p7gd2ujy5cyFuMIZorqFz_NbF4Y60Oz0,8013
10
+ claude_mpm/agents/INSTRUCTIONS.md,sha256=X6bOhSII3pZVZh_Vw_zMYRdfLtyl5Mmf_jhrVYfNxFs,7200
11
11
  claude_mpm/agents/__init__.py,sha256=r-p7ervzjLPD7_8dm2tXX_fwvdTZy6KwKA03ofxN3sA,3275
12
12
  claude_mpm/agents/agent-template.yaml,sha256=koKJn8MCAJx0QNQMHouvIZrwvw5qjPV0U-aV-YVyk6s,2036
13
13
  claude_mpm/agents/agent_loader.py,sha256=aZiTX8u0__8ueHzwney98PHfVMSkrpF3Nh-DoFlso74,18675
@@ -23,7 +23,7 @@ claude_mpm/agents/templates/documentation.json,sha256=W6gF0p2XpXrYPng7aUjbpE0Z3I
23
23
  claude_mpm/agents/templates/engineer.json,sha256=vRAr9sEgKt7_IVg2e3iZmLQFQHTzjgM-YQepS-TL6rY,8829
24
24
  claude_mpm/agents/templates/ops.json,sha256=mNoS_OS_e4Ht2drx3d7H0I18x38LX16E-mhsJn95ydQ,2899
25
25
  claude_mpm/agents/templates/qa.json,sha256=qEsJzkXbqM4pAdl4vyW1HeaQME5SvnIk4XttPWI2Dhw,2942
26
- claude_mpm/agents/templates/research.json,sha256=cfZlfJ9NMEUAb9BxqK_uo2bdRiMIt842jwQxolZ7YIM,6129
26
+ claude_mpm/agents/templates/research.json,sha256=nwqExnDvMVGih7RGzbwpYGBb1NbAdHRq3L03S4QtzKs,10180
27
27
  claude_mpm/agents/templates/security.json,sha256=T0hRMeHq54ryblR2QsBFBJtNx-mYR3VEtwQYOvx4EOU,2945
28
28
  claude_mpm/agents/templates/version_control.json,sha256=RsV0WLs58boDOzurwB75Zdol4uXf_Za0VHOqQ3Og2Rw,2923
29
29
  claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json,sha256=lLso4RHXVTQmX4A1XwF84kT59zZDblPO1xCgBj4S4x8,5060
@@ -62,7 +62,7 @@ claude_mpm/core/minimal_framework_loader.py,sha256=liYS4IyuW_aFK7yhRDZwTwT-3q09f
62
62
  claude_mpm/core/mixins.py,sha256=rTEH-7FDpNiLB8oo6mSb0CLarJklv4fDJw1xM-gr5wI,5599
63
63
  claude_mpm/core/service_registry.py,sha256=wKJUO1g4UFA4dUpE3RkIYz1Ek8kIh4XfvU1kFeLCl2Q,10529
64
64
  claude_mpm/core/session_manager.py,sha256=3rO4KGZp8Qd_cUw6OWv4jyxGCUaL_MNPgCCpnwQt12A,6581
65
- claude_mpm/core/simple_runner.py,sha256=WdgPz7qMhb9ApGNK3HnM-p4CAdvzvPGPdXsdLxp4xWQ,22473
65
+ claude_mpm/core/simple_runner.py,sha256=DRChSTgPt6g0zQUZe9cEpH9ky2aZyLnlH0bhOI63vfc,24645
66
66
  claude_mpm/core/tool_access_control.py,sha256=htZbDhC8s7D7BVqfmk0BwRrYJnlnUAk8_NeJKOaeNlg,6632
67
67
  claude_mpm/generators/__init__.py,sha256=l53aBn6kBQSDz3b6bZkMCJBcEmYnV9hHEZq8LKzXgH8,152
68
68
  claude_mpm/generators/agent_profile_generator.py,sha256=2HjOscogSyvrtQj8KwdgNPS6Ym_QvgX1BMeauQZewZA,5751
@@ -81,7 +81,7 @@ claude_mpm/hooks/builtin/ticket_extraction_hook_example.py,sha256=4wNhS2tFUXgdcv
81
81
  claude_mpm/hooks/builtin/todo_agent_prefix_hook.py,sha256=v_4w2vcZIt0bkZxqdHmgtN79yHZ1gviuhhBws0FHpIQ,10226
82
82
  claude_mpm/hooks/builtin/workflow_start_hook.py,sha256=EQrtYD9qLMLSYPl3oQinEheZAJ2i5EO_h2jhhR8lmt0,7490
83
83
  claude_mpm/hooks/claude_hooks/__init__.py,sha256=bMUwt2RzDGAcEbtDMA7vWS1uJsauOY0OixIe4pHwgQ0,129
84
- claude_mpm/hooks/claude_hooks/hook_handler.py,sha256=30YDU6hVoju-vDyhP9HdhdGo5NJ8g4reJiQokLjvSKk,16154
84
+ claude_mpm/hooks/claude_hooks/hook_handler.py,sha256=r1OqgtXw04u47FVV8Ks2ppHh8hC4xSQrj3Q3hWHuHxs,21627
85
85
  claude_mpm/hooks/claude_hooks/hook_wrapper.sh,sha256=6n0-G317jIrPuNRGnAyFvBbNM4gVzKEat_WSbpvKN-g,1742
86
86
  claude_mpm/orchestration/SUBPROCESS_DESIGN.md,sha256=YwToiT1_NXblv1XIWhWPNc2uKzDvqY2E_Nix8qK7qk0,2136
87
87
  claude_mpm/orchestration/__init__.py,sha256=C-cwldtfBCgV19mKnJa5U1XiKw1rAZvx-kK61nIdcao,205
@@ -101,13 +101,15 @@ claude_mpm/schemas/agent_schema.json,sha256=xPqYaZ8VNFyabdpEL91kufKPsWk36v6hYbqo
101
101
  claude_mpm/scripts/__init__.py,sha256=M2n9fQeyfILC8gogXvJv6ixnu7hwpqLEqLWJRaUN0MU,37
102
102
  claude_mpm/scripts/ticket.py,sha256=GmFimtTJxc927cCzJvvJH3gvoxXQtAB-W-xnuclcvNs,9350
103
103
  claude_mpm/services/__init__.py,sha256=-EBm07Lh9mjcofiQHCqyCCQJMLi9akVArPlz8i_kEOo,226
104
- claude_mpm/services/agent_deployment.py,sha256=FqxKBaTl2vQqsxN7QZPKIeLmhO-f8VW6maRBmAUNW50,40398
104
+ claude_mpm/services/agent_capabilities_generator.py,sha256=K0oO2N4yjRXmf27FF6dbWCXcugT-7uGWz5p0p0APDSg,6658
105
+ claude_mpm/services/agent_deployment.py,sha256=23nvYNyDj7QXxaiDsbwhuYhNDAv9vJ-KJI-SEHWcH5I,49837
105
106
  claude_mpm/services/agent_lifecycle_manager.py,sha256=VZBVONepomFpMqL7soaXIawS4NoaltFWKed7tU6bS3w,39057
106
107
  claude_mpm/services/agent_management_service.py,sha256=eX5n6w17b9urcogVdr4V-kXcuo7yyjORTrIihjF8PeQ,22853
107
108
  claude_mpm/services/agent_modification_tracker.py,sha256=7FRDXuCNANUnLatCgtBArG-AxZNtKbGQjgCKjnzmJ80,34050
108
109
  claude_mpm/services/agent_profile_loader.py,sha256=4D1Xj0vgqV8wN7Y3r8lijh7ghy5cVGU5t5s931sVqGc,23133
109
110
  claude_mpm/services/agent_registry.py,sha256=vn8CEW0vppj_0EY2NofmNRZEnpV70mlWiX2kAViFDRg,24374
110
111
  claude_mpm/services/base_agent_manager.py,sha256=WEcfzdMaFXmXUSoEYEPNeGu8dvqjIv53zyUU0ITrhsM,14987
112
+ claude_mpm/services/deployed_agent_discovery.py,sha256=YSycVWvxbf5QtM1FkcyVKqqA0ZG4npvTTv6jexeALkE,9591
111
113
  claude_mpm/services/framework_agent_loader.py,sha256=QdRSYRurYF3YbAXJwIGei71BffD5AqOVcV3ktRPdk7g,14018
112
114
  claude_mpm/services/framework_claude_md_generator.py,sha256=3kHmkRLHTex6HFZ4DhbLVQb48j-5dAoy1q6UW1Qf7U8,22914
113
115
  claude_mpm/services/shared_prompt_cache.py,sha256=D04lrRWyg0lHyqGcAHy7IYvRHRKSg6EOpAJwBUPa2wk,29890
@@ -116,9 +118,9 @@ claude_mpm/services/ticket_manager_di.py,sha256=pIsIGncbboKzBYSRQTO7ZX5MuQzV6iFf
116
118
  claude_mpm/services/ticketing_service_original.py,sha256=Dg3TYKsy0Z3JCqV5rlMBXeMrhrkAGxOgAMUNRZtJIhw,16680
117
119
  claude_mpm/services/framework_claude_md_generator/README.md,sha256=_-ty72t2afPagDVVUEizPkhs4BYkCeqCnZDNPgZAYtY,3511
118
120
  claude_mpm/services/framework_claude_md_generator/__init__.py,sha256=OtnwxLiJektfFtsKdkHM1X27rKkFiNd_rcf4843ziKw,7334
119
- claude_mpm/services/framework_claude_md_generator/content_assembler.py,sha256=B2AFqKsmp0K-bqM69p1ucosRrBiZPWGgujh6qa_voJQ,5000
121
+ claude_mpm/services/framework_claude_md_generator/content_assembler.py,sha256=CZlw84bBWjvK68VQhjAdLnMxXBXipZtcdyPtYWLdrKo,6590
120
122
  claude_mpm/services/framework_claude_md_generator/content_validator.py,sha256=89QSGil9_NL15ci3HsVVQmfg7MZvsJS3i_ELP5yD-gA,4583
121
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py,sha256=gnW4RU5TKMstQ8u1bGdr_BlIQb4223MzRRaqd90sMCc,4991
123
+ claude_mpm/services/framework_claude_md_generator/deployment_manager.py,sha256=G0-JBMf7WH8VScCVUbXxSpmxBP_Qy_UX4TEgc4ajHFk,6187
122
124
  claude_mpm/services/framework_claude_md_generator/section_manager.py,sha256=KbipmnUg7FD3YnVdUj4Ttrm3HMmWrDnjWC6fKX5D3tI,3222
123
125
  claude_mpm/services/framework_claude_md_generator/version_manager.py,sha256=VpJMieGEVkkKC6vyhHxKcUjPNzxBuPwD61lTyPJwxXM,4284
124
126
  claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py,sha256=HIIW34LgzTJk_ne4qoNxXgYZp3EhEisJR0SjfNjPG7o,3486
@@ -158,14 +160,16 @@ claude_mpm/ui/terminal_ui.py,sha256=E_M-L-6EuGp6L8pRpaWEhTqf-ddDXhZp5W85D0XNRPw,
158
160
  claude_mpm/utils/__init__.py,sha256=E8Hvv6ykL6rnnc8-YmfoGNpRCZbcIirxcFuNz7YvDIg,346
159
161
  claude_mpm/utils/config_manager.py,sha256=TlekZYIWOz_ouWHQU4Gc-zckhoFK9AqA25b6A_XZdDc,16412
160
162
  claude_mpm/utils/error_handler.py,sha256=W_Zc0FrKudpXvxT66Oxx0v8WkR8HA2KlynzzGy3eGcU,8168
163
+ claude_mpm/utils/framework_detection.py,sha256=nzs1qRZK9K-zT0382z1FpGDvgzUNrUg8rBL-O_WLq-Q,1217
161
164
  claude_mpm/utils/import_migration_example.py,sha256=W4a4XH3FY_VBB00BB8Lae2aRPM021PxLHzdUfEs0B5w,2463
162
165
  claude_mpm/utils/imports.py,sha256=wX-SOXUHbemx01MHRGQpVwajzXH6qYdQkYNFCIbb2mw,6851
163
166
  claude_mpm/utils/path_operations.py,sha256=6pLMnAWBVzHkgp6JyQHmHbGD-dWn-nX21yV4E_eT-kM,11614
164
167
  claude_mpm/utils/paths.py,sha256=Xv0SZWdZRkRjN9e6clBcA165ya00GNQxt7SwMz51tfA,10153
165
168
  claude_mpm/validation/__init__.py,sha256=bJ19g9lnk7yIjtxzN8XPegp87HTFBzCrGQOpFgRTf3g,155
166
169
  claude_mpm/validation/agent_validator.py,sha256=gxBn3m3NyJiHymIoNGUBk4dzRjIrw3TVL6lWPpmZmW8,11693
167
- claude_mpm-2.0.0.dist-info/METADATA,sha256=RC_YCOD4Ed-EIA2RU4THxcAwU8mqthscpZdz-XetqBg,13250
168
- claude_mpm-2.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
169
- claude_mpm-2.0.0.dist-info/entry_points.txt,sha256=PknO31um7d8bt6GjOiVeYpdJpjND0_C1z-LQfY6UfiU,142
170
- claude_mpm-2.0.0.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
171
- claude_mpm-2.0.0.dist-info/RECORD,,
170
+ claude_mpm-2.1.0.dist-info/licenses/LICENSE,sha256=cSdDfXjoTVhstrERrqme4zgxAu4GubU22zVEHsiXGxs,1071
171
+ claude_mpm-2.1.0.dist-info/METADATA,sha256=_HnaGOf8sfNGPZB7-MyF7vlxr7aIrZAeNJk4nQDWA4k,13906
172
+ claude_mpm-2.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
173
+ claude_mpm-2.1.0.dist-info/entry_points.txt,sha256=PknO31um7d8bt6GjOiVeYpdJpjND0_C1z-LQfY6UfiU,142
174
+ claude_mpm-2.1.0.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
175
+ claude_mpm-2.1.0.dist-info/RECORD,,
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Claude MPM Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.