claude-mpm 4.7.4__py3-none-any.whl → 4.7.6__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/cli/commands/configure.py +72 -14
- claude_mpm/cli/commands/mpm_init.py +75 -127
- claude_mpm/hooks/__init__.py +6 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +27 -10
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +2 -2
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory_hook_service.py +85 -3
- claude_mpm/utils/agent_dependency_loader.py +38 -18
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/METADATA +1 -1
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/RECORD +19 -17
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.7.6.dist-info}/top_level.txt +0 -0
@@ -14,7 +14,7 @@ import logging
|
|
14
14
|
import subprocess
|
15
15
|
import sys
|
16
16
|
import time
|
17
|
-
from typing import Dict, List, Optional, Set, Tuple
|
17
|
+
from typing import Any, Dict, List, Optional, Set, Tuple
|
18
18
|
|
19
19
|
from packaging.requirements import InvalidRequirement, Requirement
|
20
20
|
|
@@ -72,7 +72,7 @@ class AgentDependencyLoader:
|
|
72
72
|
Returns:
|
73
73
|
Dictionary mapping agent IDs to their file paths
|
74
74
|
"""
|
75
|
-
deployed_agents = {}
|
75
|
+
deployed_agents: Dict[str, Path] = {}
|
76
76
|
claude_agents_dir = Path.cwd() / ".claude" / "agents"
|
77
77
|
|
78
78
|
if not claude_agents_dir.exists():
|
@@ -409,7 +409,7 @@ class AgentDependencyLoader:
|
|
409
409
|
Returns:
|
410
410
|
Analysis results including missing and satisfied dependencies
|
411
411
|
"""
|
412
|
-
results = {
|
412
|
+
results: Dict[str, Any] = {
|
413
413
|
"agents": {},
|
414
414
|
"summary": {
|
415
415
|
"total_agents": len(self.deployed_agents),
|
@@ -422,7 +422,7 @@ class AgentDependencyLoader:
|
|
422
422
|
}
|
423
423
|
|
424
424
|
for agent_id, deps in self.agent_dependencies.items():
|
425
|
-
agent_result = {
|
425
|
+
agent_result: Dict[str, Dict[str, List[str]]] = {
|
426
426
|
"python": {"satisfied": [], "missing": [], "outdated": []},
|
427
427
|
"system": {"satisfied": [], "missing": []},
|
428
428
|
}
|
@@ -476,8 +476,8 @@ class AgentDependencyLoader:
|
|
476
476
|
"""
|
477
477
|
import sys
|
478
478
|
|
479
|
-
compatible = []
|
480
|
-
incompatible = []
|
479
|
+
compatible: List[str] = []
|
480
|
+
incompatible: List[str] = []
|
481
481
|
|
482
482
|
for dep in dependencies:
|
483
483
|
try:
|
@@ -593,20 +593,37 @@ class AgentDependencyLoader:
|
|
593
593
|
try:
|
594
594
|
cmd = [sys.executable, "-m", "pip", "install"]
|
595
595
|
|
596
|
-
# Check
|
596
|
+
# Check environment and add appropriate flags
|
597
|
+
import os
|
597
598
|
import sysconfig
|
598
599
|
|
599
|
-
|
600
|
-
|
601
|
-
|
600
|
+
# Check if in virtualenv
|
601
|
+
in_virtualenv = (
|
602
|
+
(hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix)
|
603
|
+
or (hasattr(sys, "real_prefix"))
|
604
|
+
or (os.environ.get("VIRTUAL_ENV") is not None)
|
605
|
+
)
|
602
606
|
|
603
|
-
if
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
)
|
609
|
-
|
607
|
+
if in_virtualenv:
|
608
|
+
# In virtualenv - no special flags needed
|
609
|
+
logger.debug("Installing in virtualenv (no special flags)")
|
610
|
+
else:
|
611
|
+
# Check for PEP 668 managed environment
|
612
|
+
stdlib_path = sysconfig.get_path("stdlib")
|
613
|
+
marker_file = Path(stdlib_path) / "EXTERNALLY-MANAGED"
|
614
|
+
parent_marker = marker_file.parent.parent / "EXTERNALLY-MANAGED"
|
615
|
+
|
616
|
+
if marker_file.exists() or parent_marker.exists():
|
617
|
+
logger.warning(
|
618
|
+
"PEP 668 managed environment detected. "
|
619
|
+
"Installing with --break-system-packages flag. "
|
620
|
+
"Consider using a virtual environment instead."
|
621
|
+
)
|
622
|
+
cmd.append("--break-system-packages")
|
623
|
+
else:
|
624
|
+
# Normal system Python - use --user
|
625
|
+
cmd.append("--user")
|
626
|
+
logger.debug("Installing with --user flag")
|
610
627
|
|
611
628
|
cmd.extend(compatible)
|
612
629
|
|
@@ -946,13 +963,16 @@ class AgentDependencyLoader:
|
|
946
963
|
|
947
964
|
def check_deployed_agent_dependencies(
|
948
965
|
auto_install: bool = False, verbose: bool = False
|
949
|
-
) ->
|
966
|
+
) -> int:
|
950
967
|
"""
|
951
968
|
Check dependencies for currently deployed agents.
|
952
969
|
|
953
970
|
Args:
|
954
971
|
auto_install: If True, automatically install missing Python dependencies
|
955
972
|
verbose: If True, enable verbose logging
|
973
|
+
|
974
|
+
Returns:
|
975
|
+
Status code: 0 if all dependencies satisfied, 1 if missing dependencies
|
956
976
|
"""
|
957
977
|
if verbose:
|
958
978
|
logging.getLogger().setLevel(logging.DEBUG)
|
@@ -0,0 +1,260 @@
|
|
1
|
+
"""
|
2
|
+
Display Helper for Rich Console Output.
|
3
|
+
|
4
|
+
WHY: Centralizes display formatting logic to reduce code duplication
|
5
|
+
across CLI commands. Provides reusable components for tables, panels,
|
6
|
+
reports, and structured output.
|
7
|
+
"""
|
8
|
+
|
9
|
+
from typing import Any, Dict, List, Tuple
|
10
|
+
|
11
|
+
from rich.console import Console
|
12
|
+
from rich.panel import Panel
|
13
|
+
from rich.table import Table
|
14
|
+
|
15
|
+
|
16
|
+
class DisplayHelper:
|
17
|
+
"""Centralized display formatting for Rich console output."""
|
18
|
+
|
19
|
+
def __init__(self, console: Console):
|
20
|
+
"""Initialize display helper with console instance."""
|
21
|
+
self.console = console
|
22
|
+
|
23
|
+
def display_separator(self, char: str = "=", width: int = 60) -> None:
|
24
|
+
"""Display a separator line."""
|
25
|
+
self.console.print(char * width)
|
26
|
+
|
27
|
+
def display_header(self, title: str, width: int = 60) -> None:
|
28
|
+
"""Display a formatted header with separators."""
|
29
|
+
self.display_separator(width=width)
|
30
|
+
self.console.print(f"[bold]{title}[/bold]")
|
31
|
+
self.display_separator(width=width)
|
32
|
+
self.console.print()
|
33
|
+
|
34
|
+
def display_section_title(self, title: str, emoji: str = "") -> None:
|
35
|
+
"""Display a section title with optional emoji."""
|
36
|
+
if emoji:
|
37
|
+
self.console.print(f"[bold cyan]{emoji} {title}[/bold cyan]")
|
38
|
+
else:
|
39
|
+
self.console.print(f"[bold cyan]{title}[/bold cyan]")
|
40
|
+
|
41
|
+
def display_key_value_table(
|
42
|
+
self,
|
43
|
+
title: str,
|
44
|
+
data: Dict[str, Any],
|
45
|
+
key_style: str = "cyan",
|
46
|
+
value_style: str = "white",
|
47
|
+
) -> None:
|
48
|
+
"""Display a two-column key-value table."""
|
49
|
+
table = Table(title=title, show_header=True)
|
50
|
+
table.add_column("Property", style=key_style)
|
51
|
+
table.add_column("Value", style=value_style)
|
52
|
+
|
53
|
+
for key, value in data.items():
|
54
|
+
# Handle various value types
|
55
|
+
if isinstance(value, bool):
|
56
|
+
display_value = "✓" if value else "✗"
|
57
|
+
elif isinstance(value, int) and key.lower().find("size") >= 0:
|
58
|
+
display_value = f"{value:,} characters"
|
59
|
+
else:
|
60
|
+
display_value = str(value)
|
61
|
+
table.add_row(key, display_value)
|
62
|
+
|
63
|
+
self.console.print(table)
|
64
|
+
|
65
|
+
def display_list_section(
|
66
|
+
self, title: str, items: List[str], max_items: int = 10, color: str = "white"
|
67
|
+
) -> None:
|
68
|
+
"""Display a titled list of items."""
|
69
|
+
self.console.print(f"\n[bold cyan]{title}[/bold cyan]")
|
70
|
+
for item in items[:max_items]:
|
71
|
+
self.console.print(f" [{color}]{item}[/{color}]")
|
72
|
+
|
73
|
+
def display_warning_list(self, title: str, items: List[str]) -> None:
|
74
|
+
"""Display a list of warning items."""
|
75
|
+
self.console.print(f"\n[yellow]{title}[/yellow]")
|
76
|
+
for item in items:
|
77
|
+
self.console.print(f" • {item}")
|
78
|
+
|
79
|
+
def display_info_list(self, title: str, items: List[str]) -> None:
|
80
|
+
"""Display a list of info items."""
|
81
|
+
self.console.print(f"\n[blue]{title}[/blue]")
|
82
|
+
for item in items[:5]:
|
83
|
+
self.console.print(f" • {item}")
|
84
|
+
|
85
|
+
def display_metric_row(
|
86
|
+
self, label: str, value: Any, indent: int = 2, warning: bool = False
|
87
|
+
) -> None:
|
88
|
+
"""Display a single metric row with label and value."""
|
89
|
+
indent_str = " " * indent
|
90
|
+
if warning:
|
91
|
+
self.console.print(f"{indent_str}[yellow]{label}: {value}[/yellow]")
|
92
|
+
else:
|
93
|
+
self.console.print(f"{indent_str}{label}: {value}")
|
94
|
+
|
95
|
+
def display_metrics_section(
|
96
|
+
self, title: str, metrics: Dict[str, Any], emoji: str = ""
|
97
|
+
) -> None:
|
98
|
+
"""Display a section with multiple metrics."""
|
99
|
+
self.display_section_title(title, emoji)
|
100
|
+
for label, value in metrics.items():
|
101
|
+
self.display_metric_row(label, value)
|
102
|
+
|
103
|
+
def display_report_section(
|
104
|
+
self,
|
105
|
+
title: str,
|
106
|
+
data: Dict[str, Any],
|
107
|
+
emoji: str = "",
|
108
|
+
show_warnings: bool = True,
|
109
|
+
) -> None:
|
110
|
+
"""Display a generic report section with data and optional warnings."""
|
111
|
+
self.display_section_title(title, emoji)
|
112
|
+
|
113
|
+
for key, value in data.items():
|
114
|
+
if isinstance(value, dict):
|
115
|
+
# Handle nested dictionaries
|
116
|
+
self.console.print(f" {key}:")
|
117
|
+
for sub_key, sub_value in value.items():
|
118
|
+
self.console.print(f" {sub_key}: {sub_value}")
|
119
|
+
elif isinstance(value, list):
|
120
|
+
# Handle lists
|
121
|
+
self.console.print(f" {key}:")
|
122
|
+
for item in value[:5]: # Limit to first 5 items
|
123
|
+
if isinstance(item, dict):
|
124
|
+
# Handle dict items in list
|
125
|
+
desc = item.get("description") or str(item)
|
126
|
+
prefix = "⚠️ " if show_warnings else "•"
|
127
|
+
self.console.print(f" {prefix} {desc}")
|
128
|
+
else:
|
129
|
+
self.console.print(f" • {item}")
|
130
|
+
else:
|
131
|
+
# Simple key-value
|
132
|
+
self.console.print(f" {key}: {value}")
|
133
|
+
|
134
|
+
def display_recommendations(self, recommendations: List[str]) -> None:
|
135
|
+
"""Display a recommendations section."""
|
136
|
+
if recommendations:
|
137
|
+
self.display_section_title("💡 Recommendations")
|
138
|
+
for rec in recommendations[:5]:
|
139
|
+
self.console.print(f" → {rec}")
|
140
|
+
|
141
|
+
def display_documentation_status(
|
142
|
+
self, analysis: Dict, title: str = "Current CLAUDE.md Status"
|
143
|
+
) -> None:
|
144
|
+
"""Display documentation status table."""
|
145
|
+
data = {
|
146
|
+
"Size": analysis.get("size", 0),
|
147
|
+
"Lines": analysis.get("lines", 0),
|
148
|
+
"Sections": len(analysis.get("sections", [])),
|
149
|
+
"Has Priority Index": analysis.get("has_priority_index", False),
|
150
|
+
"Has Priority Markers": analysis.get("has_priority_markers", False),
|
151
|
+
}
|
152
|
+
|
153
|
+
if analysis.get("last_modified"):
|
154
|
+
data["Last Modified"] = analysis["last_modified"]
|
155
|
+
|
156
|
+
self.display_key_value_table(title, data)
|
157
|
+
|
158
|
+
# Display warnings if present
|
159
|
+
if analysis.get("outdated_patterns"):
|
160
|
+
self.display_warning_list(
|
161
|
+
"⚠️ Outdated patterns detected:", analysis["outdated_patterns"]
|
162
|
+
)
|
163
|
+
|
164
|
+
# Display custom sections if present
|
165
|
+
if analysis.get("custom_sections"):
|
166
|
+
self.display_info_list(
|
167
|
+
"[INFO]️ Custom sections found:", analysis["custom_sections"]
|
168
|
+
)
|
169
|
+
|
170
|
+
def display_activity_summary(
|
171
|
+
self, summary: Dict, period: str = "Last 30 days"
|
172
|
+
) -> None:
|
173
|
+
"""Display activity summary metrics."""
|
174
|
+
metrics = {
|
175
|
+
"Total commits": summary.get("total_commits", 0),
|
176
|
+
"Active contributors": summary.get("total_authors", 0),
|
177
|
+
"Files modified": summary.get("files_changed", 0),
|
178
|
+
"Current branch": summary.get("current_branch", "unknown"),
|
179
|
+
}
|
180
|
+
|
181
|
+
self.display_metrics_section(
|
182
|
+
f"📊 Activity Overview ({period.lower()})", metrics
|
183
|
+
)
|
184
|
+
|
185
|
+
if summary.get("has_uncommitted"):
|
186
|
+
self.display_metric_row(
|
187
|
+
"⚠️ Uncommitted changes",
|
188
|
+
f"{summary.get('uncommitted_count', 0)} files",
|
189
|
+
warning=True,
|
190
|
+
)
|
191
|
+
|
192
|
+
def display_commit_list(
|
193
|
+
self, commits: List[Dict], title: str = "📝 Recent Commits (last 10)"
|
194
|
+
) -> None:
|
195
|
+
"""Display a list of commits."""
|
196
|
+
if commits:
|
197
|
+
self.display_section_title(title)
|
198
|
+
for commit in commits[:10]:
|
199
|
+
msg = commit.get("message", "")[:60]
|
200
|
+
hash_val = commit.get("hash", "")
|
201
|
+
author = commit.get("author", "")
|
202
|
+
self.console.print(f" [{hash_val}] {msg} - {author}")
|
203
|
+
|
204
|
+
def display_file_change_list(
|
205
|
+
self, files: List[Tuple[str, int]], title: str = "🔥 Most Changed Files"
|
206
|
+
) -> None:
|
207
|
+
"""Display a list of changed files with change counts."""
|
208
|
+
if files:
|
209
|
+
self.display_section_title(title)
|
210
|
+
for file_path, changes in files[:10]:
|
211
|
+
self.console.print(f" {file_path}: {changes} changes")
|
212
|
+
|
213
|
+
def display_branch_list(
|
214
|
+
self,
|
215
|
+
branches: List[str],
|
216
|
+
current_branch: str,
|
217
|
+
title: str = "🌿 Active Branches",
|
218
|
+
) -> None:
|
219
|
+
"""Display a list of branches with current branch marked."""
|
220
|
+
if branches:
|
221
|
+
self.display_section_title(title)
|
222
|
+
for branch in branches:
|
223
|
+
marker = "→" if branch == current_branch else " "
|
224
|
+
self.console.print(f" {marker} {branch}")
|
225
|
+
|
226
|
+
def display_success_panel(
|
227
|
+
self,
|
228
|
+
title: str,
|
229
|
+
content: str,
|
230
|
+
border_style: str = "green",
|
231
|
+
) -> None:
|
232
|
+
"""Display a success panel with content."""
|
233
|
+
self.console.print(Panel(content, title=title, border_style=border_style))
|
234
|
+
|
235
|
+
def display_info_panel(
|
236
|
+
self,
|
237
|
+
title: str,
|
238
|
+
content: str,
|
239
|
+
border_style: str = "cyan",
|
240
|
+
) -> None:
|
241
|
+
"""Display an info panel with content."""
|
242
|
+
self.console.print(Panel(content, title=title, border_style=border_style))
|
243
|
+
|
244
|
+
def display_files_list(
|
245
|
+
self, title: str, files: List[str], prefix: str = "•"
|
246
|
+
) -> None:
|
247
|
+
"""Display a list of files."""
|
248
|
+
if files:
|
249
|
+
self.console.print(f"[bold]{title}[/bold]")
|
250
|
+
for file in files:
|
251
|
+
self.console.print(f" {prefix} {file}")
|
252
|
+
self.console.print()
|
253
|
+
|
254
|
+
def display_next_steps(self, steps: List[str]) -> None:
|
255
|
+
"""Display next steps list."""
|
256
|
+
if steps:
|
257
|
+
self.console.print("[bold]Next Steps:[/bold]")
|
258
|
+
for step in steps:
|
259
|
+
self.console.print(f" → {step}")
|
260
|
+
self.console.print()
|
@@ -9,6 +9,7 @@ DESIGN DECISION: We implement exponential backoff for retries and provide
|
|
9
9
|
multiple installation strategies (pip, conda, source) to maximize success rate.
|
10
10
|
"""
|
11
11
|
|
12
|
+
import os
|
12
13
|
import re
|
13
14
|
import subprocess
|
14
15
|
import sys
|
@@ -80,6 +81,7 @@ class RobustPackageInstaller:
|
|
80
81
|
self.use_cache = use_cache
|
81
82
|
self.attempts: List[InstallAttempt] = []
|
82
83
|
self.success_cache: Dict[str, bool] = {}
|
84
|
+
self.in_virtualenv = self._check_virtualenv()
|
83
85
|
self.is_pep668_managed = self._check_pep668_managed()
|
84
86
|
self.pep668_warning_shown = False
|
85
87
|
|
@@ -201,6 +203,35 @@ class RobustPackageInstaller:
|
|
201
203
|
except Exception as e:
|
202
204
|
return False, f"Unexpected error: {e!s}"
|
203
205
|
|
206
|
+
def _check_virtualenv(self) -> bool:
|
207
|
+
"""
|
208
|
+
Check if running inside a virtual environment.
|
209
|
+
|
210
|
+
WHY: Virtual environments are already isolated and don't need
|
211
|
+
--user or --break-system-packages flags. In fact, using --user
|
212
|
+
in a virtualenv causes errors.
|
213
|
+
|
214
|
+
Returns:
|
215
|
+
True if in a virtualenv, False otherwise
|
216
|
+
"""
|
217
|
+
# Multiple ways to detect virtualenv
|
218
|
+
return (
|
219
|
+
(
|
220
|
+
# venv creates sys.base_prefix
|
221
|
+
hasattr(sys, "base_prefix")
|
222
|
+
and sys.base_prefix != sys.prefix
|
223
|
+
)
|
224
|
+
or (
|
225
|
+
# virtualenv creates sys.real_prefix
|
226
|
+
hasattr(sys, "real_prefix")
|
227
|
+
)
|
228
|
+
or (
|
229
|
+
# VIRTUAL_ENV environment variable
|
230
|
+
os.environ.get("VIRTUAL_ENV")
|
231
|
+
is not None
|
232
|
+
)
|
233
|
+
)
|
234
|
+
|
204
235
|
def _check_pep668_managed(self) -> bool:
|
205
236
|
"""
|
206
237
|
Check if Python environment is PEP 668 externally managed.
|
@@ -211,6 +242,11 @@ class RobustPackageInstaller:
|
|
211
242
|
Returns:
|
212
243
|
True if PEP 668 managed, False otherwise
|
213
244
|
"""
|
245
|
+
# If in virtualenv, PEP 668 doesn't apply
|
246
|
+
if self.in_virtualenv:
|
247
|
+
logger.debug("Running in virtualenv, PEP 668 restrictions don't apply")
|
248
|
+
return False
|
249
|
+
|
214
250
|
# Check for EXTERNALLY-MANAGED marker file
|
215
251
|
stdlib_path = sysconfig.get_path("stdlib")
|
216
252
|
marker_file = Path(stdlib_path) / "EXTERNALLY-MANAGED"
|
@@ -240,7 +276,7 @@ class RobustPackageInstaller:
|
|
240
276
|
"Your Python installation is marked as externally managed (PEP 668).\n"
|
241
277
|
"This typically means you're using a system Python managed by Homebrew, apt, etc.\n"
|
242
278
|
"\n"
|
243
|
-
"Installing packages with --break-system-packages
|
279
|
+
"Installing packages with --break-system-packages flag...\n"
|
244
280
|
"\n"
|
245
281
|
"RECOMMENDED: Use a virtual environment instead:\n"
|
246
282
|
" python -m venv .venv\n"
|
@@ -255,8 +291,10 @@ class RobustPackageInstaller:
|
|
255
291
|
"""
|
256
292
|
Build the installation command for a given strategy.
|
257
293
|
|
258
|
-
WHY:
|
259
|
-
|
294
|
+
WHY: Proper environment detection ensures we use the right pip flags:
|
295
|
+
- Virtualenv: No special flags needed (already isolated)
|
296
|
+
- PEP 668 system: Use --break-system-packages only
|
297
|
+
- Normal system: Use --user for user-local install
|
260
298
|
|
261
299
|
Args:
|
262
300
|
package_spec: Package specification
|
@@ -267,14 +305,19 @@ class RobustPackageInstaller:
|
|
267
305
|
"""
|
268
306
|
base_cmd = [sys.executable, "-m", "pip", "install"]
|
269
307
|
|
270
|
-
#
|
271
|
-
if self.
|
308
|
+
# Determine appropriate flags based on environment
|
309
|
+
if self.in_virtualenv:
|
310
|
+
# In virtualenv - no special flags needed
|
311
|
+
logger.debug("Installing in virtualenv (no special flags)")
|
312
|
+
elif self.is_pep668_managed:
|
313
|
+
# System Python with PEP 668 - use --break-system-packages only
|
272
314
|
self._show_pep668_warning()
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
)
|
315
|
+
base_cmd.append("--break-system-packages")
|
316
|
+
logger.debug("Added --break-system-packages flag for PEP 668 environment")
|
317
|
+
else:
|
318
|
+
# Normal system Python - use --user for user-local install
|
319
|
+
base_cmd.append("--user")
|
320
|
+
logger.debug("Added --user flag for user-local installation")
|
278
321
|
|
279
322
|
# Add cache control
|
280
323
|
if not self.use_cache:
|
@@ -612,11 +655,16 @@ class RobustPackageInstaller:
|
|
612
655
|
try:
|
613
656
|
cmd = [sys.executable, "-m", "pip", "install"]
|
614
657
|
|
615
|
-
# Add
|
616
|
-
if self.
|
658
|
+
# Add appropriate flags based on environment
|
659
|
+
if self.in_virtualenv:
|
660
|
+
logger.debug("Batch install in virtualenv (no special flags)")
|
661
|
+
elif self.is_pep668_managed:
|
617
662
|
self._show_pep668_warning()
|
618
|
-
cmd.
|
619
|
-
logger.debug("Added
|
663
|
+
cmd.append("--break-system-packages")
|
664
|
+
logger.debug("Added --break-system-packages for batch installation")
|
665
|
+
else:
|
666
|
+
cmd.append("--user")
|
667
|
+
logger.debug("Added --user flag for batch installation")
|
620
668
|
|
621
669
|
cmd.extend(packages)
|
622
670
|
|
@@ -654,12 +702,18 @@ class RobustPackageInstaller:
|
|
654
702
|
lines.append("INSTALLATION REPORT")
|
655
703
|
lines.append("=" * 60)
|
656
704
|
|
657
|
-
# Add
|
658
|
-
|
659
|
-
|
705
|
+
# Add environment status
|
706
|
+
lines.append("")
|
707
|
+
if self.in_virtualenv:
|
708
|
+
lines.append("✓ Environment: Virtual Environment (isolated)")
|
709
|
+
lines.append(" No special pip flags needed")
|
710
|
+
elif self.is_pep668_managed:
|
660
711
|
lines.append("⚠️ PEP 668 Managed Environment: YES")
|
661
|
-
lines.append(" Installations used --break-system-packages
|
712
|
+
lines.append(" Installations used --break-system-packages flag")
|
662
713
|
lines.append(" Consider using a virtual environment for better isolation")
|
714
|
+
else:
|
715
|
+
lines.append("Environment: System Python")
|
716
|
+
lines.append(" Installations used --user flag for user-local install")
|
663
717
|
|
664
718
|
# Summary
|
665
719
|
total_attempts = len(self.attempts)
|
@@ -672,7 +726,7 @@ class RobustPackageInstaller:
|
|
672
726
|
lines.append("")
|
673
727
|
|
674
728
|
# Details by package
|
675
|
-
packages = {}
|
729
|
+
packages: Dict[str, List[InstallAttempt]] = {}
|
676
730
|
for attempt in self.attempts:
|
677
731
|
if attempt.package not in packages:
|
678
732
|
packages[attempt.package] = []
|
@@ -1,5 +1,5 @@
|
|
1
1
|
claude_mpm/BUILD_NUMBER,sha256=9JfxhnDtr-8l3kCP2U5TVXSErptHoga8m7XA8zqgGOc,4
|
2
|
-
claude_mpm/VERSION,sha256=
|
2
|
+
claude_mpm/VERSION,sha256=gVLWgYgcXVc7Af4ejsObqWB0dhZ1OktjUoRmgOIPx1M,6
|
3
3
|
claude_mpm/__init__.py,sha256=UCw6j9e_tZQ3kJtTqmdfNv7MHyw9nD1jkj80WurwM2g,2064
|
4
4
|
claude_mpm/__main__.py,sha256=Ro5UBWBoQaSAIoSqWAr7zkbLyvi4sSy28WShqAhKJG0,723
|
5
5
|
claude_mpm/constants.py,sha256=cChN3myrAcF3jC-6DvHnBFTEnwlDk-TAsIXPvUZr_yw,5953
|
@@ -79,7 +79,7 @@ claude_mpm/cli/commands/analyze_code.py,sha256=yWZpG0aL4XlhcthtvbUqnFSlnvvseWO3V
|
|
79
79
|
claude_mpm/cli/commands/cleanup.py,sha256=TukZoPVfAFSF4ICfKCQUibczDE73EJP8nbEbfuT8GhE,19768
|
80
80
|
claude_mpm/cli/commands/cleanup_orphaned_agents.py,sha256=JR8crvgrz7Sa6d-SI-gKywok5S9rwc_DzDVk_h85sVs,4467
|
81
81
|
claude_mpm/cli/commands/config.py,sha256=Yfi8WO-10_MYz2QipFw-yEzVvHKNQ6iSQXeyW5J85Cg,18559
|
82
|
-
claude_mpm/cli/commands/configure.py,sha256=
|
82
|
+
claude_mpm/cli/commands/configure.py,sha256=22wvCVGeIUFk2mBvvG9Lhd-Jzq8GRLmGg0W9mndxMOY,82489
|
83
83
|
claude_mpm/cli/commands/dashboard.py,sha256=4jPTmTl97DRNNJlYREWeE1iDdkct1uL-vv24MZn9fj4,11403
|
84
84
|
claude_mpm/cli/commands/debug.py,sha256=YCfJ3aYf6hOCvLW_grdfINdEqI4RXVS28VJ7tkZBFS8,47115
|
85
85
|
claude_mpm/cli/commands/doctor.py,sha256=nNKLZG3Qv_UsHNgrmetrWKgS7Pe2Jn5vq5aXyl60wKQ,7310
|
@@ -96,7 +96,7 @@ claude_mpm/cli/commands/mcp_setup_external.py,sha256=hfBHkaioNa0JRDhahNEc8agyrUw
|
|
96
96
|
claude_mpm/cli/commands/mcp_tool_commands.py,sha256=q17GzlFT3JiLTrDqwPO2tz1-fKmPO5QU449syTnKTz4,1283
|
97
97
|
claude_mpm/cli/commands/memory.py,sha256=O4T5HGL-Ob_QPt2dZHQvoOrVohnaDKrBjyngq1Mcv1w,26185
|
98
98
|
claude_mpm/cli/commands/monitor.py,sha256=Fjb68hf3dEwTFek2LV8Nh6iU0qEkY7qYlOn32IwNaNg,9566
|
99
|
-
claude_mpm/cli/commands/mpm_init.py,sha256=
|
99
|
+
claude_mpm/cli/commands/mpm_init.py,sha256=H7op69CaE7VPOViTuEiCTeANe708ZAcJpkpgbfG2baM,60311
|
100
100
|
claude_mpm/cli/commands/mpm_init_handler.py,sha256=b1CSwZYJ89wMorKzPOKS-RVxOKR2kT9yv9KQLvKkd2U,3532
|
101
101
|
claude_mpm/cli/commands/run.py,sha256=PB2H55piOPTy4yo4OBgbUCjMlcz9K79wbwpxQVc9m5Q,48225
|
102
102
|
claude_mpm/cli/commands/search.py,sha256=_0qbUnop8v758MHsB0fAop8FVxwygD59tec_-iN7pLE,9806
|
@@ -222,7 +222,6 @@ claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css,sha256=
|
|
222
222
|
claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css,sha256=v6uB3hr2dU7aGodvQVxu1y-bM-pN-jeOD_-iwGG7mIc,603
|
223
223
|
claude_mpm/dashboard/react/components/shared/FilterBar.module.css,sha256=Ea-dpAlKoY7WobxLESQsNvLUVjFhJlQvLygCY8-47Vk,1690
|
224
224
|
claude_mpm/dashboard/static/events.html,sha256=iKBH2gqxhU6JTmSglAVyNJkWA9c11L4Dxn40otAfnAU,17952
|
225
|
-
claude_mpm/dashboard/static/index-hub-backup.html,sha256=5N7toUxcTQJgqwGPyk8J7kvzR71WCdMpy3F8niM-ZK0,26044
|
226
225
|
claude_mpm/dashboard/static/index.html,sha256=F971Wwl0opHFb-SKD3fi0tvZmrzMPLh7MkJsJzR9tAc,31192
|
227
226
|
claude_mpm/dashboard/static/monitors.html,sha256=waNCJiIGWBvve7nbzvihnVDjaP49FPfFSNqOpkwiIaM,14229
|
228
227
|
claude_mpm/dashboard/static/socket.io.min.js,sha256=c-uha8iV_fpFTifsuA3vMe3o2GH5nhdf-TsRDqvsBE8,49993
|
@@ -369,10 +368,12 @@ claude_mpm/experimental/__init__.py,sha256=R_aclOvWpvSTHWAx9QXyg9OIPVK2dXT5tQJhx
|
|
369
368
|
claude_mpm/experimental/cli_enhancements.py,sha256=PfAt-SI-crBoE0Dtx1JecpS5_6OT_0apJbo28KS6HUI,11541
|
370
369
|
claude_mpm/generators/__init__.py,sha256=rG8vwF_BjPmeMKvyMXpUA8uJ-7mtW2HTNfalZzgRlNk,153
|
371
370
|
claude_mpm/generators/agent_profile_generator.py,sha256=yTEFdZPUt4lAfXlQuIIxzRwOrWMaJhEJ3Z6Ofm48Rlc,5740
|
372
|
-
claude_mpm/hooks/__init__.py,sha256=
|
371
|
+
claude_mpm/hooks/__init__.py,sha256=y-mfGUb4xTCENUIj4RfAhK2oJTIL0qMI2gDatdf52nc,567
|
373
372
|
claude_mpm/hooks/base_hook.py,sha256=wKbT_0g3dhvkA48pTz4GJpZQw8URhaT0LpZnCc7CEas,5026
|
374
373
|
claude_mpm/hooks/instruction_reinforcement.py,sha256=PnjfDSZ_72gbzHnRoug7qtXfpW5d1cxnmittpnPd2ws,11059
|
375
|
-
claude_mpm/hooks/
|
374
|
+
claude_mpm/hooks/kuzu_enrichment_hook.py,sha256=jghoEZX8fA6HZ1kM_5l93cuCyy-AMBjWp-nPW5EgaTk,8729
|
375
|
+
claude_mpm/hooks/kuzu_memory_hook.py,sha256=ockbKXXc69Yiryq2uWNCAUpSxtN8eqAec9i5BB1MRaI,12265
|
376
|
+
claude_mpm/hooks/kuzu_response_hook.py,sha256=iyVrsOrGpp-VFOjKC5GUnXro088Ftex-vHmfHsmAUv8,6136
|
376
377
|
claude_mpm/hooks/memory_integration_hook.py,sha256=F8Hf35hmbmhxi-qHQJac4zoWIr60ob3PCHa4P_rbxO8,16635
|
377
378
|
claude_mpm/hooks/tool_call_interceptor.py,sha256=tYUBJHjbtaI5-HSWcz0aeUW0CaiQPypuDOTULQ0BCNI,7506
|
378
379
|
claude_mpm/hooks/validation_hooks.py,sha256=i5uOaXifItwJfIdjjLCxAwrkKdkmo2Qa4qMc5-dwsKw,6465
|
@@ -417,8 +418,8 @@ claude_mpm/services/exceptions.py,sha256=5lVZETr_6-xk0ItH7BTfYUiX5RlckS1e8ah_Ual
|
|
417
418
|
claude_mpm/services/hook_installer_service.py,sha256=x3H3bFVlmhK4Ue1K279f44lwMEw3W1p3zoETGfjIH_w,19708
|
418
419
|
claude_mpm/services/hook_service.py,sha256=I6JILbackBsdvrDNQ9TeGSB7XNqozNRP26T4E9_ROtU,15693
|
419
420
|
claude_mpm/services/mcp_config_manager.py,sha256=W_zlFXzaQ64BoM4FuOJ47ywUUw0Rcf_u_ivvrpt2ZZY,67241
|
420
|
-
claude_mpm/services/mcp_service_verifier.py,sha256=
|
421
|
-
claude_mpm/services/memory_hook_service.py,sha256=
|
421
|
+
claude_mpm/services/mcp_service_verifier.py,sha256=xOo1SqbQ1J07TnJ_aNN7yCjna4UBZwnQQu6RrNCgoNc,25604
|
422
|
+
claude_mpm/services/memory_hook_service.py,sha256=BZhCYFpWV_7FguDL0MY4k8JOZJFmCbYWNMfDywM9G5Q,15304
|
422
423
|
claude_mpm/services/monitor_build_service.py,sha256=8gWR9CaqgXdG6-OjOFXGpk28GCcJTlHhojkUYnMCebI,12160
|
423
424
|
claude_mpm/services/orphan_detection.py,sha256=cEFE96FhC6EJSa53rUjbgjDj_E1_Ej-0KoYDQST22t0,26339
|
424
425
|
claude_mpm/services/port_manager.py,sha256=83GJ1uSF9pXsECXHtf4M8jBHzOptdh3Lpt7t0GyY2Wc,22838
|
@@ -568,7 +569,7 @@ claude_mpm/services/diagnostics/checks/filesystem_check.py,sha256=V5HoHDYlSuoK2l
|
|
568
569
|
claude_mpm/services/diagnostics/checks/installation_check.py,sha256=JdTqZreriAavN8gkHTaaKwclwnvfaRw87Np9mDfUXlk,19548
|
569
570
|
claude_mpm/services/diagnostics/checks/instructions_check.py,sha256=VbgBorl0RpFvxKQ_SC1gibTmGSiXaKSp-vVZt6hbH1g,16290
|
570
571
|
claude_mpm/services/diagnostics/checks/mcp_check.py,sha256=eG8BVWclwRRYh6G1ew1Z_DE1ksRirRxEy3fIe3cu58k,12174
|
571
|
-
claude_mpm/services/diagnostics/checks/mcp_services_check.py,sha256=
|
572
|
+
claude_mpm/services/diagnostics/checks/mcp_services_check.py,sha256=y6hpDMl3ZoT9WXIgxgbPaebgPqmgfiFruoed7224xos,43776
|
572
573
|
claude_mpm/services/diagnostics/checks/monitor_check.py,sha256=hZk301gvM8XAnfcOdtzE-e9XMBW3hgmDwSVxVSmF9CY,10097
|
573
574
|
claude_mpm/services/diagnostics/checks/startup_log_check.py,sha256=qQQI9Ezk7Sa5NpvJrtDY_0bWhoLPASZJn0hpNR8pEsI,12341
|
574
575
|
claude_mpm/services/event_bus/__init__.py,sha256=ETCo4a6puIeyVWAv55uCDjjhzNyUwbVAHEcAVkVapx8,688
|
@@ -762,7 +763,7 @@ claude_mpm/tools/code_tree_builder.py,sha256=8EaW94NjEObraiW811dDoQ8xKixrzCr4YoL
|
|
762
763
|
claude_mpm/tools/code_tree_events.py,sha256=10tf9ZGkPIXzWqYvwq0SIJdIOwKNnxgKWYOmRzVGeLc,13396
|
763
764
|
claude_mpm/tools/socketio_debug.py,sha256=QpG_GoN9VY8OZ0tcg8bqIF2oB_ZbKTjGp0oD0xYmsFo,22226
|
764
765
|
claude_mpm/utils/__init__.py,sha256=rkxNE0tDfKEN2lr2LLBuToNSvkF-yjF38607eUXL1vk,353
|
765
|
-
claude_mpm/utils/agent_dependency_loader.py,sha256=
|
766
|
+
claude_mpm/utils/agent_dependency_loader.py,sha256=A_OliEjBIwJn2e2N_7RLsh2zIhC5KdDLQTlMMV2DByc,36678
|
766
767
|
claude_mpm/utils/common.py,sha256=6hcs3Y6lx596Oj4H3CEQId-NIn8XEZJw1Ud3GAKwXKA,14341
|
767
768
|
claude_mpm/utils/config_manager.py,sha256=iWsPM0uo31Ela-XhFe9DIw3RuVxJf94_yFQ1HkibAlY,15876
|
768
769
|
claude_mpm/utils/console.py,sha256=2Agd91xj5NSMgvfUFJIUwVnpghnKjrd8EYH7inF12M4,279
|
@@ -770,6 +771,7 @@ claude_mpm/utils/database_connector.py,sha256=7Fa9gzr19Y-5eJuvCGfBYJRjMfI6s-EIB6
|
|
770
771
|
claude_mpm/utils/dependency_cache.py,sha256=GmdSYmV6YSmvtaoeAR2vGZpD3ormFsHpooKJqYgOZa0,11780
|
771
772
|
claude_mpm/utils/dependency_manager.py,sha256=g9iYA_uyZ4XE8cY-VfhKYd1NA3aqr9ZYT3IBTv_abmY,7356
|
772
773
|
claude_mpm/utils/dependency_strategies.py,sha256=m-VyZP0KF8z1mCcd_dEPNZ8WbU8z0GyBpvw210yCNvM,12149
|
774
|
+
claude_mpm/utils/display_helper.py,sha256=Ce2TGGOqMLq3o7L5ax9YtxNaFuNisLb97Cdoe4Y5Gjs,9783
|
773
775
|
claude_mpm/utils/environment_context.py,sha256=mCnRJqQLTyaAv-7M4bp9N9WqVgfSQb5xbbfgvFxGHJA,10141
|
774
776
|
claude_mpm/utils/error_handler.py,sha256=RWL7DnXttJKCgYhevUm9XlMC33rEhX2CXo1IiCtwV4g,7969
|
775
777
|
claude_mpm/utils/file_utils.py,sha256=pv3MEKLsn4WIOra5JoHnCm_FaJbNcKMuS3EKuXAWyLc,7859
|
@@ -778,15 +780,15 @@ claude_mpm/utils/import_migration_example.py,sha256=sKlV-apfkHDJzzez6uubHXjx91YF
|
|
778
780
|
claude_mpm/utils/imports.py,sha256=IGcW0W6V-2jTmkVlO-l0Zodo3LRA3zkaumD9J2qn7dE,6654
|
779
781
|
claude_mpm/utils/log_cleanup.py,sha256=1d8K1V2uOFPGJJKFOk6E_AMj22sifAibOg-VQyGooWo,22301
|
780
782
|
claude_mpm/utils/path_operations.py,sha256=gvd6Ye5rMFxIKnFzWwIL6jYy8wGkjSH3onYAan6zXkA,10869
|
781
|
-
claude_mpm/utils/robust_installer.py,sha256=
|
783
|
+
claude_mpm/utils/robust_installer.py,sha256=ixif5ExezKr5eOtgoY7W629tcDm-lZtUe5_Igkq7ZYQ,27108
|
782
784
|
claude_mpm/utils/session_logging.py,sha256=_6eoyCvVKhu2OhgRzC5FvMfFnD9et75lzCqARbd_i-k,3059
|
783
785
|
claude_mpm/utils/subprocess_utils.py,sha256=D0izRT8anjiUb_JG72zlJR_JAw1cDkb7kalNmfX9KlM,10443
|
784
786
|
claude_mpm/validation/__init__.py,sha256=YZhwE3mhit-lslvRLuwfX82xJ_k4haZeKmh4IWaVwtk,156
|
785
787
|
claude_mpm/validation/agent_validator.py,sha256=GprtAvu80VyMXcKGsK_VhYiXWA6BjKHv7O6HKx0AB9w,20917
|
786
788
|
claude_mpm/validation/frontmatter_validator.py,sha256=YpJlYNNYcV8u6hIOi3_jaRsDnzhbcQpjCBE6eyBKaFY,7076
|
787
|
-
claude_mpm-4.7.
|
788
|
-
claude_mpm-4.7.
|
789
|
-
claude_mpm-4.7.
|
790
|
-
claude_mpm-4.7.
|
791
|
-
claude_mpm-4.7.
|
792
|
-
claude_mpm-4.7.
|
789
|
+
claude_mpm-4.7.6.dist-info/licenses/LICENSE,sha256=lpaivOlPuBZW1ds05uQLJJswy8Rp_HMNieJEbFlqvLk,1072
|
790
|
+
claude_mpm-4.7.6.dist-info/METADATA,sha256=zrxNvScK7d0H2C78k6Wuq_mJ3rQHbjCWTfzoC0JvWNQ,17517
|
791
|
+
claude_mpm-4.7.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
792
|
+
claude_mpm-4.7.6.dist-info/entry_points.txt,sha256=Vlw3GNi-OtTpKSrez04iNrPmxNxYDpIWxmJCxiZ5Tx8,526
|
793
|
+
claude_mpm-4.7.6.dist-info/top_level.txt,sha256=1nUg3FEaBySgm8t-s54jK5zoPnu3_eY6EP6IOlekyHA,11
|
794
|
+
claude_mpm-4.7.6.dist-info/RECORD,,
|