claude-mpm 3.7.4__py3-none-any.whl → 3.7.8__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/INSTRUCTIONS.md +18 -0
  3. claude_mpm/agents/schema/agent_schema.json +1 -1
  4. claude_mpm/agents/templates/code_analyzer.json +26 -11
  5. claude_mpm/agents/templates/data_engineer.json +3 -6
  6. claude_mpm/agents/templates/documentation.json +2 -2
  7. claude_mpm/agents/templates/engineer.json +1 -1
  8. claude_mpm/agents/templates/ops.json +3 -8
  9. claude_mpm/agents/templates/qa.json +2 -3
  10. claude_mpm/agents/templates/research.json +1 -2
  11. claude_mpm/agents/templates/security.json +2 -5
  12. claude_mpm/agents/templates/ticketing.json +3 -3
  13. claude_mpm/agents/templates/version_control.json +3 -3
  14. claude_mpm/agents/templates/web_qa.json +3 -3
  15. claude_mpm/agents/templates/web_ui.json +3 -3
  16. claude_mpm/cli/commands/agents.py +118 -1
  17. claude_mpm/cli/parser.py +11 -0
  18. claude_mpm/core/framework_loader.py +8 -7
  19. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +46 -2
  20. claude_mpm/dashboard/templates/index.html +5 -5
  21. claude_mpm/services/agents/deployment/agent_deployment.py +5 -1
  22. claude_mpm/services/agents/deployment/async_agent_deployment.py +5 -1
  23. claude_mpm/services/agents/management/agent_capabilities_generator.py +21 -11
  24. claude_mpm/services/ticket_manager.py +207 -44
  25. claude_mpm/utils/agent_dependency_loader.py +66 -15
  26. claude_mpm/utils/robust_installer.py +587 -0
  27. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/METADATA +17 -21
  28. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/RECORD +32 -47
  29. claude_mpm/.claude-mpm/logs/hooks_20250728.log +0 -10
  30. claude_mpm/agents/agent-template.yaml +0 -83
  31. claude_mpm/cli/README.md +0 -108
  32. claude_mpm/cli_module/refactoring_guide.md +0 -253
  33. claude_mpm/config/async_logging_config.yaml +0 -145
  34. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
  35. claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
  36. claude_mpm/dashboard/README.md +0 -121
  37. claude_mpm/dashboard/static/js/dashboard.js.backup +0 -1973
  38. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
  39. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
  40. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
  41. claude_mpm/hooks/README.md +0 -96
  42. claude_mpm/schemas/agent_schema.json +0 -435
  43. claude_mpm/services/framework_claude_md_generator/README.md +0 -92
  44. claude_mpm/services/version_control/VERSION +0 -1
  45. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/WHEEL +0 -0
  46. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/entry_points.txt +0 -0
  47. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/licenses/LICENSE +0 -0
  48. {claude_mpm-3.7.4.dist-info → claude_mpm-3.7.8.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,587 @@
1
+ """
2
+ Robust dependency installer with retry logic and fallback strategies.
3
+
4
+ WHY: Network issues and temporary unavailability can cause dependency installation
5
+ to fail. This module provides resilient installation with automatic retries,
6
+ fallback strategies, and clear error reporting.
7
+
8
+ DESIGN DECISION: We implement exponential backoff for retries and provide
9
+ multiple installation strategies (pip, conda, source) to maximize success rate.
10
+ """
11
+
12
+ import subprocess
13
+ import sys
14
+ import time
15
+ import json
16
+ import re
17
+ from pathlib import Path
18
+ from typing import List, Tuple, Optional, Dict, Any
19
+ from enum import Enum
20
+ from dataclasses import dataclass
21
+
22
+ from ..core.logger import get_logger
23
+
24
+ logger = get_logger(__name__)
25
+
26
+
27
+ class InstallStrategy(Enum):
28
+ """Available installation strategies."""
29
+ PIP = "pip"
30
+ PIP_NO_DEPS = "pip_no_deps"
31
+ PIP_UPGRADE = "pip_upgrade"
32
+ PIP_INDEX_URL = "pip_index_url"
33
+ SOURCE = "source"
34
+
35
+
36
+ @dataclass
37
+ class InstallAttempt:
38
+ """Record of an installation attempt."""
39
+ strategy: InstallStrategy
40
+ package: str
41
+ success: bool
42
+ error: Optional[str]
43
+ duration: float
44
+ retry_count: int
45
+
46
+
47
+ class RobustPackageInstaller:
48
+ """
49
+ Robust package installer with retry logic and multiple strategies.
50
+
51
+ WHY: This class handles the complexity of package installation in various
52
+ environments, network conditions, and Python versions. It ensures maximum
53
+ success rate while providing clear feedback on failures.
54
+ """
55
+
56
+ def __init__(
57
+ self,
58
+ max_retries: int = 3,
59
+ retry_delay: float = 2.0,
60
+ timeout: int = 300,
61
+ use_cache: bool = True
62
+ ):
63
+ """
64
+ Initialize robust installer.
65
+
66
+ Args:
67
+ max_retries: Maximum number of retry attempts per package
68
+ retry_delay: Initial delay between retries (uses exponential backoff)
69
+ timeout: Maximum time for each installation attempt in seconds
70
+ use_cache: Whether to use pip cache
71
+ """
72
+ self.max_retries = max_retries
73
+ self.retry_delay = retry_delay
74
+ self.timeout = timeout
75
+ self.use_cache = use_cache
76
+ self.attempts: List[InstallAttempt] = []
77
+ self.success_cache: Dict[str, bool] = {}
78
+
79
+ def install_package(
80
+ self,
81
+ package_spec: str,
82
+ strategies: Optional[List[InstallStrategy]] = None
83
+ ) -> Tuple[bool, Optional[str]]:
84
+ """
85
+ Install a package using robust retry logic and multiple strategies.
86
+
87
+ WHY: Single installation attempts often fail due to transient issues.
88
+ This method tries multiple strategies with retries to maximize success.
89
+
90
+ Args:
91
+ package_spec: Package specification (e.g., "pandas>=2.0.0")
92
+ strategies: List of strategies to try (defaults to sensible order)
93
+
94
+ Returns:
95
+ Tuple of (success, error_message)
96
+ """
97
+ # Check success cache first
98
+ if package_spec in self.success_cache:
99
+ if self.success_cache[package_spec]:
100
+ logger.debug(f"Package {package_spec} already successfully installed")
101
+ return True, None
102
+
103
+ # Default strategy order
104
+ if strategies is None:
105
+ strategies = [
106
+ InstallStrategy.PIP,
107
+ InstallStrategy.PIP_UPGRADE,
108
+ InstallStrategy.PIP_NO_DEPS,
109
+ InstallStrategy.PIP_INDEX_URL,
110
+ ]
111
+
112
+ # Extract package name for special handling
113
+ package_name = self._extract_package_name(package_spec)
114
+
115
+ # Special handling for known problematic packages
116
+ if self._needs_special_handling(package_name):
117
+ strategies = self._get_special_strategies(package_name)
118
+
119
+ # Try each strategy with retries
120
+ for strategy in strategies:
121
+ for retry in range(self.max_retries):
122
+ start_time = time.time()
123
+
124
+ # Calculate delay with exponential backoff
125
+ if retry > 0:
126
+ delay = self.retry_delay * (2 ** (retry - 1))
127
+ logger.info(f"Retry {retry}/{self.max_retries} after {delay:.1f}s delay...")
128
+ time.sleep(delay)
129
+
130
+ # Attempt installation
131
+ success, error = self._attempt_install(package_spec, strategy)
132
+ duration = time.time() - start_time
133
+
134
+ # Record attempt
135
+ self.attempts.append(InstallAttempt(
136
+ strategy=strategy,
137
+ package=package_spec,
138
+ success=success,
139
+ error=error,
140
+ duration=duration,
141
+ retry_count=retry
142
+ ))
143
+
144
+ if success:
145
+ logger.info(f"Successfully installed {package_spec} using {strategy.value}")
146
+ self.success_cache[package_spec] = True
147
+ return True, None
148
+
149
+ # Check if error is retryable
150
+ if not self._is_retryable_error(error):
151
+ logger.warning(f"Non-retryable error for {package_spec}: {error}")
152
+ break
153
+
154
+ # All attempts failed
155
+ self.success_cache[package_spec] = False
156
+ final_error = self._get_consolidated_error(package_spec)
157
+ return False, final_error
158
+
159
+ def _attempt_install(
160
+ self,
161
+ package_spec: str,
162
+ strategy: InstallStrategy
163
+ ) -> Tuple[bool, Optional[str]]:
164
+ """
165
+ Attempt to install a package using a specific strategy.
166
+
167
+ Args:
168
+ package_spec: Package specification
169
+ strategy: Installation strategy to use
170
+
171
+ Returns:
172
+ Tuple of (success, error_message)
173
+ """
174
+ try:
175
+ cmd = self._build_install_command(package_spec, strategy)
176
+ logger.debug(f"Running: {' '.join(cmd)}")
177
+
178
+ result = subprocess.run(
179
+ cmd,
180
+ capture_output=True,
181
+ text=True,
182
+ timeout=self.timeout
183
+ )
184
+
185
+ if result.returncode == 0:
186
+ # Verify installation
187
+ if self._verify_installation(package_spec):
188
+ return True, None
189
+ else:
190
+ return False, "Package installed but verification failed"
191
+ else:
192
+ error_msg = self._extract_error_message(result.stderr)
193
+ logger.debug(f"Installation failed: {error_msg}")
194
+ return False, error_msg
195
+
196
+ except subprocess.TimeoutExpired:
197
+ return False, f"Installation timed out after {self.timeout}s"
198
+ except Exception as e:
199
+ return False, f"Unexpected error: {str(e)}"
200
+
201
+ def _build_install_command(
202
+ self,
203
+ package_spec: str,
204
+ strategy: InstallStrategy
205
+ ) -> List[str]:
206
+ """
207
+ Build the installation command for a given strategy.
208
+
209
+ Args:
210
+ package_spec: Package specification
211
+ strategy: Installation strategy
212
+
213
+ Returns:
214
+ Command as list of arguments
215
+ """
216
+ base_cmd = [sys.executable, "-m", "pip", "install"]
217
+
218
+ # Add cache control
219
+ if not self.use_cache:
220
+ base_cmd.append("--no-cache-dir")
221
+
222
+ if strategy == InstallStrategy.PIP:
223
+ return base_cmd + [package_spec]
224
+
225
+ elif strategy == InstallStrategy.PIP_NO_DEPS:
226
+ return base_cmd + ["--no-deps", package_spec]
227
+
228
+ elif strategy == InstallStrategy.PIP_UPGRADE:
229
+ return base_cmd + ["--upgrade", package_spec]
230
+
231
+ elif strategy == InstallStrategy.PIP_INDEX_URL:
232
+ # Try alternative index (PyPI mirror)
233
+ return base_cmd + [
234
+ "--index-url", "https://pypi.org/simple",
235
+ "--extra-index-url", "https://pypi.python.org/simple",
236
+ package_spec
237
+ ]
238
+
239
+ else:
240
+ return base_cmd + [package_spec]
241
+
242
+ def _extract_package_name(self, package_spec: str) -> str:
243
+ """
244
+ Extract package name from specification.
245
+
246
+ Args:
247
+ package_spec: Package specification (e.g., "pandas>=2.0.0")
248
+
249
+ Returns:
250
+ Package name (e.g., "pandas")
251
+ """
252
+ # Remove version specifiers
253
+ match = re.match(r'^([a-zA-Z0-9_-]+)', package_spec)
254
+ if match:
255
+ return match.group(1)
256
+ return package_spec
257
+
258
+ def _needs_special_handling(self, package_name: str) -> bool:
259
+ """
260
+ Check if package needs special installation handling.
261
+
262
+ Args:
263
+ package_name: Name of the package
264
+
265
+ Returns:
266
+ True if package needs special handling
267
+ """
268
+ # Known problematic packages
269
+ special_packages = {
270
+ 'tree-sitter-ruby',
271
+ 'tree-sitter-php',
272
+ 'tree-sitter-javascript',
273
+ 'tree-sitter-typescript',
274
+ 'tree-sitter-go',
275
+ 'tree-sitter-rust',
276
+ 'tree-sitter-java',
277
+ 'tree-sitter-cpp',
278
+ 'tree-sitter-c',
279
+ }
280
+
281
+ return package_name.lower() in special_packages
282
+
283
+ def _get_special_strategies(self, package_name: str) -> List[InstallStrategy]:
284
+ """
285
+ Get special installation strategies for problematic packages.
286
+
287
+ Args:
288
+ package_name: Name of the package
289
+
290
+ Returns:
291
+ List of strategies to try
292
+ """
293
+ # For tree-sitter packages, try upgrade first (often fixes version conflicts)
294
+ if package_name.startswith('tree-sitter-'):
295
+ return [
296
+ InstallStrategy.PIP_UPGRADE,
297
+ InstallStrategy.PIP,
298
+ InstallStrategy.PIP_INDEX_URL,
299
+ InstallStrategy.PIP_NO_DEPS,
300
+ ]
301
+
302
+ return [InstallStrategy.PIP, InstallStrategy.PIP_UPGRADE]
303
+
304
+ def _verify_installation(self, package_spec: str) -> bool:
305
+ """
306
+ Verify that a package was successfully installed.
307
+
308
+ Args:
309
+ package_spec: Package specification
310
+
311
+ Returns:
312
+ True if package is installed and importable
313
+ """
314
+ package_name = self._extract_package_name(package_spec)
315
+
316
+ # Convert package name to import name (e.g., tree-sitter-ruby -> tree_sitter_ruby)
317
+ import_name = package_name.replace('-', '_')
318
+
319
+ try:
320
+ # Check if package is installed
321
+ import importlib.metadata
322
+ try:
323
+ version = importlib.metadata.version(package_name)
324
+ logger.debug(f"Package {package_name} version {version} is installed")
325
+
326
+ # For tree-sitter packages, don't try to import (they have C extensions)
327
+ if package_name.startswith('tree-sitter-'):
328
+ return True
329
+
330
+ # Try to import the package
331
+ try:
332
+ __import__(import_name)
333
+ return True
334
+ except ImportError:
335
+ # Some packages have different import names, that's OK
336
+ return True
337
+
338
+ except importlib.metadata.PackageNotFoundError:
339
+ return False
340
+
341
+ except ImportError:
342
+ # Fallback for older Python versions
343
+ try:
344
+ import pkg_resources
345
+ pkg_resources.get_distribution(package_name)
346
+ return True
347
+ except pkg_resources.DistributionNotFound:
348
+ return False
349
+
350
+ def _is_retryable_error(self, error: Optional[str]) -> bool:
351
+ """
352
+ Determine if an error is worth retrying.
353
+
354
+ Args:
355
+ error: Error message
356
+
357
+ Returns:
358
+ True if error is retryable
359
+ """
360
+ if not error:
361
+ return False
362
+
363
+ # Retryable error patterns
364
+ retryable_patterns = [
365
+ 'connection', 'timeout', 'temporary failure',
366
+ 'network', 'unreachable', 'could not find',
367
+ 'no matching distribution', 'httperror',
368
+ 'http error', 'ssl', 'certificate',
369
+ 'readtimeout', 'connectionerror'
370
+ ]
371
+
372
+ error_lower = error.lower()
373
+ return any(pattern in error_lower for pattern in retryable_patterns)
374
+
375
+ def _extract_error_message(self, stderr: str) -> str:
376
+ """
377
+ Extract meaningful error message from pip stderr.
378
+
379
+ Args:
380
+ stderr: Standard error output from pip
381
+
382
+ Returns:
383
+ Extracted error message
384
+ """
385
+ if not stderr:
386
+ return "Unknown error"
387
+
388
+ # Look for ERROR: lines
389
+ error_lines = []
390
+ for line in stderr.splitlines():
391
+ if 'ERROR:' in line:
392
+ error_lines.append(line.split('ERROR:', 1)[1].strip())
393
+
394
+ if error_lines:
395
+ return ' | '.join(error_lines)
396
+
397
+ # Fall back to last non-empty line
398
+ lines = [l.strip() for l in stderr.splitlines() if l.strip()]
399
+ if lines:
400
+ return lines[-1]
401
+
402
+ return "Installation failed"
403
+
404
+ def _get_consolidated_error(self, package_spec: str) -> str:
405
+ """
406
+ Get a consolidated error message from all attempts.
407
+
408
+ Args:
409
+ package_spec: Package specification that failed
410
+
411
+ Returns:
412
+ Consolidated error message
413
+ """
414
+ # Get unique error messages from attempts
415
+ errors = set()
416
+ for attempt in self.attempts:
417
+ if attempt.package == package_spec and attempt.error:
418
+ errors.add(attempt.error)
419
+
420
+ if not errors:
421
+ return f"Failed to install {package_spec} after {len(self.attempts)} attempts"
422
+
423
+ # Format error message
424
+ if len(errors) == 1:
425
+ return list(errors)[0]
426
+ else:
427
+ return f"Multiple errors: {' | '.join(errors)}"
428
+
429
+ def install_packages(
430
+ self,
431
+ packages: List[str],
432
+ parallel: bool = False
433
+ ) -> Tuple[List[str], List[str], Dict[str, str]]:
434
+ """
435
+ Install multiple packages with robust error handling.
436
+
437
+ Args:
438
+ packages: List of package specifications
439
+ parallel: Whether to attempt parallel installation
440
+
441
+ Returns:
442
+ Tuple of (successful_packages, failed_packages, error_map)
443
+ """
444
+ successful = []
445
+ failed = []
446
+ errors = {}
447
+
448
+ # Group packages that can be installed together
449
+ if parallel and len(packages) > 1:
450
+ # Try to install all at once first
451
+ logger.info(f"Attempting batch installation of {len(packages)} packages...")
452
+ success, error = self._attempt_batch_install(packages)
453
+
454
+ if success:
455
+ logger.info("Batch installation successful")
456
+ return packages, [], {}
457
+ else:
458
+ logger.warning(f"Batch installation failed: {error}")
459
+ logger.info("Falling back to individual installation...")
460
+
461
+ # Install packages individually
462
+ for i, package in enumerate(packages, 1):
463
+ logger.info(f"Installing package {i}/{len(packages)}: {package}")
464
+
465
+ success, error = self.install_package(package)
466
+
467
+ if success:
468
+ successful.append(package)
469
+ else:
470
+ failed.append(package)
471
+ errors[package] = error or "Unknown error"
472
+
473
+ return successful, failed, errors
474
+
475
+ def _attempt_batch_install(self, packages: List[str]) -> Tuple[bool, Optional[str]]:
476
+ """
477
+ Attempt to install multiple packages in a single pip command.
478
+
479
+ Args:
480
+ packages: List of package specifications
481
+
482
+ Returns:
483
+ Tuple of (success, error_message)
484
+ """
485
+ try:
486
+ cmd = [sys.executable, "-m", "pip", "install"] + packages
487
+
488
+ result = subprocess.run(
489
+ cmd,
490
+ capture_output=True,
491
+ text=True,
492
+ timeout=self.timeout * 2 # Longer timeout for batch
493
+ )
494
+
495
+ if result.returncode == 0:
496
+ # Verify all packages
497
+ all_verified = all(
498
+ self._verify_installation(pkg) for pkg in packages
499
+ )
500
+ if all_verified:
501
+ return True, None
502
+ else:
503
+ return False, "Some packages failed verification"
504
+ else:
505
+ error_msg = self._extract_error_message(result.stderr)
506
+ return False, error_msg
507
+
508
+ except subprocess.TimeoutExpired:
509
+ return False, f"Batch installation timed out"
510
+ except Exception as e:
511
+ return False, f"Batch installation error: {str(e)}"
512
+
513
+ def get_report(self) -> str:
514
+ """
515
+ Generate a report of installation attempts.
516
+
517
+ Returns:
518
+ Formatted report string
519
+ """
520
+ lines = []
521
+ lines.append("=" * 60)
522
+ lines.append("INSTALLATION REPORT")
523
+ lines.append("=" * 60)
524
+
525
+ # Summary
526
+ total_attempts = len(self.attempts)
527
+ successful = sum(1 for a in self.attempts if a.success)
528
+ failed = total_attempts - successful
529
+
530
+ lines.append(f"Total attempts: {total_attempts}")
531
+ lines.append(f"Successful: {successful}")
532
+ lines.append(f"Failed: {failed}")
533
+ lines.append("")
534
+
535
+ # Details by package
536
+ packages = {}
537
+ for attempt in self.attempts:
538
+ if attempt.package not in packages:
539
+ packages[attempt.package] = []
540
+ packages[attempt.package].append(attempt)
541
+
542
+ for package, attempts in packages.items():
543
+ success = any(a.success for a in attempts)
544
+ status = "✓" if success else "✗"
545
+ lines.append(f"{status} {package}:")
546
+
547
+ for attempt in attempts:
548
+ retry_str = f" (retry {attempt.retry_count})" if attempt.retry_count > 0 else ""
549
+ result = "success" if attempt.success else f"failed: {attempt.error}"
550
+ lines.append(f" - {attempt.strategy.value}{retry_str}: {result}")
551
+
552
+ lines.append("=" * 60)
553
+ return "\n".join(lines)
554
+
555
+
556
+ def install_with_retry(
557
+ packages: List[str],
558
+ max_retries: int = 3,
559
+ verbose: bool = False
560
+ ) -> Tuple[bool, str]:
561
+ """
562
+ Convenience function to install packages with retry logic.
563
+
564
+ Args:
565
+ packages: List of package specifications
566
+ max_retries: Maximum retry attempts
567
+ verbose: Whether to print verbose output
568
+
569
+ Returns:
570
+ Tuple of (all_success, error_message)
571
+ """
572
+ if verbose:
573
+ import logging
574
+ logging.getLogger().setLevel(logging.DEBUG)
575
+
576
+ installer = RobustPackageInstaller(max_retries=max_retries)
577
+ successful, failed, errors = installer.install_packages(packages)
578
+
579
+ if verbose:
580
+ print(installer.get_report())
581
+
582
+ if failed:
583
+ error_msg = f"Failed to install {len(failed)} packages: "
584
+ error_msg += ", ".join(f"{pkg} ({errors[pkg]})" for pkg in failed)
585
+ return False, error_msg
586
+
587
+ return True, ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-mpm
3
- Version: 3.7.4
3
+ Version: 3.7.8
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
@@ -30,7 +30,6 @@ Requires-Dist: flask>=3.0.0
30
30
  Requires-Dist: flask-cors>=4.0.0
31
31
  Requires-Dist: watchdog>=3.0.0
32
32
  Requires-Dist: tree-sitter>=0.21.0
33
- Requires-Dist: tree-sitter-language-pack>=0.8.0
34
33
  Requires-Dist: python-socketio>=5.11.0
35
34
  Requires-Dist: aiohttp>=3.9.0
36
35
  Requires-Dist: aiohttp-cors>=0.8.0
@@ -47,53 +46,48 @@ Requires-Dist: flake8; extra == "dev"
47
46
  Requires-Dist: mypy; extra == "dev"
48
47
  Provides-Extra: monitor
49
48
  Provides-Extra: agents
50
- Requires-Dist: allure-pytest>=2.13.0; extra == "agents"
51
- Requires-Dist: ansible>=9.0.0; extra == "agents"
52
- Requires-Dist: apache-airflow>=2.8.0; extra == "agents"
53
49
  Requires-Dist: bandit>=1.7.5; extra == "agents"
54
50
  Requires-Dist: black>=23.0.0; extra == "agents"
55
- Requires-Dist: checkov>=3.1.0; extra == "agents"
56
51
  Requires-Dist: commitizen>=3.13.0; extra == "agents"
57
- Requires-Dist: cryptography>=41.0.0; extra == "agents"
58
52
  Requires-Dist: dask>=2023.12.0; extra == "agents"
59
53
  Requires-Dist: detect-secrets>=1.4.0; extra == "agents"
60
54
  Requires-Dist: diagrams>=0.23.0; extra == "agents"
61
- Requires-Dist: docker>=7.0.0; extra == "agents"
62
55
  Requires-Dist: docstring-parser>=0.15.0; extra == "agents"
63
56
  Requires-Dist: faker>=20.0.0; extra == "agents"
64
57
  Requires-Dist: gitlint>=0.19.0; extra == "agents"
65
58
  Requires-Dist: gitpython>=3.1.40; extra == "agents"
66
- Requires-Dist: great-expectations>=0.18.0; extra == "agents"
67
59
  Requires-Dist: hypothesis>=6.92.0; extra == "agents"
68
60
  Requires-Dist: isort>=5.12.0; extra == "agents"
69
- Requires-Dist: kubernetes>=28.0.0; extra == "agents"
70
61
  Requires-Dist: lizard>=1.17.0; extra == "agents"
71
62
  Requires-Dist: mermaid-py>=0.2.0; extra == "agents"
72
63
  Requires-Dist: mkdocs>=1.5.0; extra == "agents"
73
64
  Requires-Dist: mutmut>=2.4.0; extra == "agents"
74
65
  Requires-Dist: mypy>=1.8.0; extra == "agents"
75
66
  Requires-Dist: pandas>=2.1.0; extra == "agents"
76
- Requires-Dist: pip-audit>=2.6.0; extra == "agents"
77
67
  Requires-Dist: pre-commit>=3.5.0; extra == "agents"
78
68
  Requires-Dist: prometheus-client>=0.19.0; extra == "agents"
79
69
  Requires-Dist: pydoc-markdown>=4.8.0; extra == "agents"
80
70
  Requires-Dist: pydriller>=2.5.0; extra == "agents"
81
71
  Requires-Dist: pygments>=2.17.0; extra == "agents"
82
- Requires-Dist: pyjwt>=2.8.0; extra == "agents"
83
72
  Requires-Dist: pytest>=7.4.0; extra == "agents"
84
73
  Requires-Dist: pytest-benchmark>=4.0.0; extra == "agents"
85
74
  Requires-Dist: pytest-cov>=4.1.0; extra == "agents"
86
75
  Requires-Dist: radon>=6.0.0; extra == "agents"
87
76
  Requires-Dist: rope>=1.11.0; extra == "agents"
88
- Requires-Dist: safety>=3.0.0; extra == "agents"
89
- Requires-Dist: semgrep>=1.45.0; extra == "agents"
90
77
  Requires-Dist: sphinx>=7.2.0; extra == "agents"
91
78
  Requires-Dist: sqlalchemy>=2.0.0; extra == "agents"
92
79
  Requires-Dist: sqlparse>=0.4.4; extra == "agents"
93
- Requires-Dist: terraform-compliance>=1.3.0; extra == "agents"
94
80
  Requires-Dist: tree-sitter>=0.21.0; extra == "agents"
95
- Requires-Dist: tree-sitter-language-pack>=0.8.0; extra == "agents"
96
- Requires-Dist: ydata-profiling>=4.6.0; extra == "agents"
81
+ Requires-Dist: tree-sitter-python>=0.21.0; extra == "agents"
82
+ Requires-Dist: tree-sitter-javascript>=0.21.0; extra == "agents"
83
+ Requires-Dist: tree-sitter-typescript>=0.21.0; extra == "agents"
84
+ Requires-Dist: tree-sitter-go>=0.21.0; extra == "agents"
85
+ Requires-Dist: tree-sitter-rust>=0.21.0; extra == "agents"
86
+ Requires-Dist: tree-sitter-java>=0.21.0; extra == "agents"
87
+ Requires-Dist: tree-sitter-cpp>=0.21.0; extra == "agents"
88
+ Requires-Dist: tree-sitter-c>=0.21.0; extra == "agents"
89
+ Requires-Dist: tree-sitter-ruby>=0.21.0; extra == "agents"
90
+ Requires-Dist: tree-sitter-php>=0.21.0; extra == "agents"
97
91
  Dynamic: author-email
98
92
  Dynamic: home-page
99
93
  Dynamic: license-file
@@ -118,19 +112,21 @@ A powerful orchestration framework for Claude Code that enables multi-agent work
118
112
  ## Installation
119
113
 
120
114
  ```bash
121
- # Install from PyPI
115
+ # Basic installation - pure Python, no compilation required
122
116
  pip install claude-mpm
123
117
 
124
118
  # Install with development dependencies
125
119
  pip install "claude-mpm[dev]"
126
120
 
127
- # Install with agent dependencies (recommended for full functionality)
121
+ # Install with agent dependencies - pure Python tools
128
122
  pip install "claude-mpm[agents]"
129
123
 
130
124
  # Install with all optional dependencies
131
125
  pip install "claude-mpm[agents,dev]"
132
126
  ```
133
127
 
128
+ All dependencies are pure Python - no Rust or compilation required. The `agents` dependency group includes tools for testing, code analysis, documentation, and development workflows.
129
+
134
130
  ## Basic Usage
135
131
 
136
132
  ```bash
@@ -164,10 +160,10 @@ For detailed usage, see [QUICKSTART.md](QUICKSTART.md)
164
160
 
165
161
  ### Agent Dependencies
166
162
 
167
- Claude MPM automatically manages Python dependencies required by agents. Agents can declare their dependencies in their configuration files, and the system aggregates them for easy installation.
163
+ Claude MPM automatically manages Python dependencies required by agents. All dependencies are pure Python packages that don't require compilation. Agents can declare their dependencies in their configuration files, and the system aggregates them for easy installation.
168
164
 
169
165
  ```bash
170
- # Install all agent dependencies
166
+ # Install all agent dependencies (pure Python)
171
167
  pip install "claude-mpm[agents]"
172
168
 
173
169
  # View current agent dependencies