claude-mpm 3.4.0__py3-none-any.whl → 3.4.3__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.
@@ -23,6 +23,7 @@ while preserving essential information.
23
23
  """
24
24
 
25
25
  import re
26
+ import os
26
27
  from pathlib import Path
27
28
  from typing import Dict, List, Optional, Any, Tuple
28
29
  from datetime import datetime
@@ -109,8 +110,9 @@ class MemoryBuilder(LoggerMixin):
109
110
  super().__init__()
110
111
  self.config = config or Config()
111
112
  self.project_root = PathResolver.get_project_root()
112
- self.working_directory = working_directory or self.project_root
113
- self.memories_dir = self.project_root / ".claude-mpm" / "memories"
113
+ # Use current working directory by default, not project root
114
+ self.working_directory = working_directory or Path(os.getcwd())
115
+ self.memories_dir = self.working_directory / ".claude-mpm" / "memories"
114
116
  self.router = MemoryRouter(config)
115
117
  self.project_analyzer = ProjectAnalyzer(config, self.working_directory)
116
118
 
@@ -23,6 +23,7 @@ information than lose important insights.
23
23
  """
24
24
 
25
25
  import re
26
+ import os
26
27
  from pathlib import Path
27
28
  from typing import Dict, List, Optional, Any, Set, Tuple
28
29
  from datetime import datetime
@@ -57,16 +58,19 @@ class MemoryOptimizer(LoggerMixin):
57
58
  'low': ['note', 'tip', 'hint', 'example', 'reference']
58
59
  }
59
60
 
60
- def __init__(self, config: Optional[Config] = None):
61
+ def __init__(self, config: Optional[Config] = None, working_directory: Optional[Path] = None):
61
62
  """Initialize the memory optimizer.
62
63
 
63
64
  Args:
64
65
  config: Optional Config object
66
+ working_directory: Optional working directory. If not provided, uses current working directory.
65
67
  """
66
68
  super().__init__()
67
69
  self.config = config or Config()
68
70
  self.project_root = PathResolver.get_project_root()
69
- self.memories_dir = self.project_root / ".claude-mpm" / "memories"
71
+ # Use current working directory by default, not project root
72
+ self.working_directory = working_directory or Path(os.getcwd())
73
+ self.memories_dir = self.working_directory / ".claude-mpm" / "memories"
70
74
 
71
75
  def optimize_agent_memory(self, agent_id: str) -> Dict[str, Any]:
72
76
  """Optimize memory for a specific agent.
@@ -118,6 +118,68 @@ class MemoryRouter(LoggerMixin):
118
118
  'Project Coordination', 'Team Communication',
119
119
  'Process Improvements', 'Risk Management'
120
120
  ]
121
+ },
122
+ 'data_engineer': {
123
+ 'keywords': [
124
+ 'data', 'database', 'sql', 'pipeline', 'etl', 'elt', 'extract', 'transform',
125
+ 'load', 'analytics', 'warehouse', 'lake', 'schema', 'migration',
126
+ 'replication', 'streaming', 'batch', 'kafka', 'spark', 'hadoop',
127
+ 'mongodb', 'postgres', 'mysql', 'redis', 'elasticsearch', 'index',
128
+ 'query', 'optimization', 'performance', 'partitioning', 'sharding',
129
+ 'normalization', 'denormalization', 'aggregation', 'cleansing',
130
+ 'validation', 'quality', 'lineage', 'governance', 'backup', 'restore',
131
+ 'ai api', 'openai', 'claude', 'llm', 'embedding', 'vector database'
132
+ ],
133
+ 'sections': [
134
+ 'Database Architecture Patterns', 'Pipeline Design Strategies',
135
+ 'Data Quality Standards', 'Performance Optimization Techniques'
136
+ ]
137
+ },
138
+ 'test_integration': {
139
+ 'keywords': [
140
+ 'integration', 'e2e', 'end-to-end', 'system test', 'workflow test',
141
+ 'cross-system', 'api test', 'contract test', 'service test',
142
+ 'boundary test', 'interface test', 'component test', 'smoke test',
143
+ 'acceptance test', 'scenario test', 'user journey', 'flow test',
144
+ 'regression', 'compatibility', 'interoperability', 'validation',
145
+ 'verification', 'mock', 'stub', 'test data', 'test environment',
146
+ 'test setup', 'teardown', 'isolation', 'coordination', 'synchronization',
147
+ 'selenium', 'cypress', 'playwright', 'postman', 'newman'
148
+ ],
149
+ 'sections': [
150
+ 'Integration Test Patterns', 'Cross-System Validation',
151
+ 'Test Environment Management', 'End-to-End Workflow Testing'
152
+ ]
153
+ },
154
+ 'ops': {
155
+ 'keywords': [
156
+ 'deployment', 'infrastructure', 'devops', 'cicd', 'ci/cd', 'docker',
157
+ 'container', 'kubernetes', 'helm', 'terraform', 'ansible', 'jenkins',
158
+ 'pipeline', 'build', 'release', 'staging', 'production', 'environment',
159
+ 'monitoring', 'logging', 'metrics', 'alerts', 'observability',
160
+ 'scaling', 'load balancer', 'proxy', 'nginx', 'apache', 'server',
161
+ 'network', 'firewall', 'vpc', 'aws', 'azure', 'gcp', 'cloud',
162
+ 'backup', 'disaster recovery', 'failover', 'redundancy', 'uptime',
163
+ 'prometheus', 'grafana', 'splunk', 'datadog', 'newrelic'
164
+ ],
165
+ 'sections': [
166
+ 'Deployment Strategies', 'Infrastructure Patterns',
167
+ 'Monitoring and Observability', 'Scaling and Performance'
168
+ ]
169
+ },
170
+ 'version_control': {
171
+ 'keywords': [
172
+ 'git', 'github', 'gitlab', 'bitbucket', 'branch', 'merge', 'commit',
173
+ 'pull request', 'merge request', 'tag', 'release', 'version', 'changelog',
174
+ 'semantic versioning', 'semver', 'workflow', 'gitflow', 'conflict',
175
+ 'resolution', 'rebase', 'cherry-pick', 'stash', 'bisect', 'blame',
176
+ 'diff', 'patch', 'submodule', 'hook', 'pre-commit', 'post-commit',
177
+ 'repository', 'remote', 'origin', 'upstream', 'fork', 'clone'
178
+ ],
179
+ 'sections': [
180
+ 'Branching Strategies', 'Release Management',
181
+ 'Version Control Workflows', 'Collaboration Patterns'
182
+ ]
121
183
  }
122
184
  }
123
185
 
@@ -133,6 +195,31 @@ class MemoryRouter(LoggerMixin):
133
195
  super().__init__()
134
196
  self.config = config or Config()
135
197
 
198
+ def get_supported_agents(self) -> List[str]:
199
+ """Get list of supported agent types.
200
+
201
+ WHY: Other components need to know which agent types are supported
202
+ for validation and UI display purposes.
203
+
204
+ Returns:
205
+ List of supported agent type names
206
+ """
207
+ return list(self.AGENT_PATTERNS.keys())
208
+
209
+ def is_agent_supported(self, agent_type: str) -> bool:
210
+ """Check if an agent type is supported by the memory router.
211
+
212
+ WHY: Provides validation for agent types before attempting routing.
213
+ This prevents errors and provides clear feedback about unsupported types.
214
+
215
+ Args:
216
+ agent_type: Agent type to check
217
+
218
+ Returns:
219
+ True if agent type is supported, False otherwise
220
+ """
221
+ return agent_type in self.AGENT_PATTERNS
222
+
136
223
  def analyze_and_route(self, content: str, context: Optional[Dict] = None) -> Dict[str, Any]:
137
224
  """Analyze content and determine target agent for memory storage.
138
225
 
@@ -187,7 +274,9 @@ class MemoryRouter(LoggerMixin):
187
274
  "section": "Recent Learnings",
188
275
  "confidence": 0.1,
189
276
  "reasoning": f"Error during analysis, defaulting to {self.DEFAULT_AGENT}",
190
- "error": str(e)
277
+ "error": str(e),
278
+ "timestamp": datetime.now().isoformat(),
279
+ "content_length": len(content) if content else 0
191
280
  }
192
281
 
193
282
  def test_routing_patterns(self, test_cases: List[Dict[str, str]]) -> List[Dict[str, Any]]:
@@ -283,17 +372,20 @@ class MemoryRouter(LoggerMixin):
283
372
  matched_keywords = []
284
373
 
285
374
  for keyword in patterns['keywords']:
286
- # Exact keyword match
375
+ # Exact keyword match gets higher score
287
376
  if keyword in content:
288
- score += 1.0
377
+ # Multi-word keywords get bonus score
378
+ bonus = 1.5 if ' ' in keyword else 1.0
379
+ score += bonus
289
380
  matched_keywords.append(keyword)
290
381
  # Partial match (word contains keyword)
291
382
  elif any(keyword in word for word in content.split()):
292
383
  score += 0.5
293
384
 
294
- # Normalize score by number of keywords for this agent
385
+ # Normalize score by square root to avoid penalizing agents with many keywords
295
386
  if patterns['keywords']:
296
- score = score / len(patterns['keywords'])
387
+ import math
388
+ score = score / math.sqrt(len(patterns['keywords']))
297
389
 
298
390
  scores[agent] = {
299
391
  'score': score,
@@ -361,7 +453,8 @@ class MemoryRouter(LoggerMixin):
361
453
  best_agent = agent
362
454
 
363
455
  # If no clear winner, use default
364
- if best_score < 0.1:
456
+ # Lowered threshold to handle diverse agent patterns better
457
+ if best_score < 0.05:
365
458
  return self.DEFAULT_AGENT, 0.1
366
459
 
367
460
  # Convert score to confidence (0.0 to 1.0)