claude-mpm 4.3.20__py3-none-any.whl → 4.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/agent_loader.py +2 -2
- claude_mpm/agents/agent_loader_integration.py +2 -2
- claude_mpm/agents/async_agent_loader.py +2 -2
- claude_mpm/agents/base_agent_loader.py +2 -2
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/system_agent_config.py +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -2
- claude_mpm/cli/commands/doctor.py +2 -2
- claude_mpm/cli/commands/mpm_init.py +560 -47
- claude_mpm/cli/commands/mpm_init_handler.py +6 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +39 -1
- claude_mpm/cli/startup_logging.py +11 -9
- claude_mpm/commands/mpm-init.md +76 -12
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/paths.py +2 -2
- claude_mpm/core/agent_name_normalizer.py +2 -2
- claude_mpm/core/config.py +2 -1
- claude_mpm/core/config_aliases.py +2 -2
- claude_mpm/core/file_utils.py +1 -0
- claude_mpm/core/log_manager.py +2 -2
- claude_mpm/core/tool_access_control.py +2 -2
- claude_mpm/core/unified_agent_registry.py +2 -2
- claude_mpm/core/unified_paths.py +2 -2
- claude_mpm/experimental/cli_enhancements.py +3 -2
- claude_mpm/hooks/base_hook.py +2 -2
- claude_mpm/hooks/instruction_reinforcement.py +2 -2
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/hooks/validation_hooks.py +2 -2
- claude_mpm/scripts/mpm_doctor.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +2 -2
- claude_mpm/services/agents/loading/base_agent_manager.py +2 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +2 -2
- claude_mpm/services/agents/management/agent_management_service.py +2 -2
- claude_mpm/services/agents/memory/content_manager.py +5 -2
- claude_mpm/services/agents/memory/memory_categorization_service.py +5 -2
- claude_mpm/services/agents/memory/memory_file_service.py +28 -6
- claude_mpm/services/agents/memory/memory_format_service.py +5 -2
- claude_mpm/services/agents/memory/memory_limits_service.py +4 -2
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +2 -2
- claude_mpm/services/agents/registry/modification_tracker.py +4 -4
- claude_mpm/services/async_session_logger.py +2 -1
- claude_mpm/services/claude_session_logger.py +2 -2
- claude_mpm/services/core/path_resolver.py +3 -2
- claude_mpm/services/diagnostics/diagnostic_runner.py +4 -3
- claude_mpm/services/event_bus/direct_relay.py +2 -1
- claude_mpm/services/event_bus/event_bus.py +2 -1
- claude_mpm/services/event_bus/relay.py +2 -2
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +2 -2
- claude_mpm/services/infrastructure/daemon_manager.py +2 -2
- claude_mpm/services/memory/cache/simple_cache.py +2 -2
- claude_mpm/services/project/archive_manager.py +981 -0
- claude_mpm/services/project/documentation_manager.py +536 -0
- claude_mpm/services/project/enhanced_analyzer.py +491 -0
- claude_mpm/services/project/project_organizer.py +904 -0
- claude_mpm/services/response_tracker.py +2 -2
- claude_mpm/services/socketio/handlers/connection.py +14 -33
- claude_mpm/services/socketio/server/eventbus_integration.py +2 -2
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +473 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +643 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +804 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +661 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +696 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +557 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +486 -0
- claude_mpm/services/unified/deployment_strategies/local.py +594 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +672 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +499 -0
- claude_mpm/services/unified/migration.py +532 -0
- claude_mpm/services/unified/strategies.py +551 -0
- claude_mpm/services/unified/unified_analyzer.py +534 -0
- claude_mpm/services/unified/unified_config.py +688 -0
- claude_mpm/services/unified/unified_deployment.py +470 -0
- claude_mpm/services/version_control/version_parser.py +5 -4
- claude_mpm/storage/state_storage.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +49 -0
- claude_mpm/utils/common.py +542 -0
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/error_handler.py +2 -1
- claude_mpm/utils/log_cleanup.py +2 -2
- claude_mpm/utils/path_operations.py +2 -2
- claude_mpm/utils/robust_installer.py +56 -0
- claude_mpm/utils/session_logging.py +2 -2
- claude_mpm/utils/subprocess_utils.py +2 -2
- claude_mpm/validation/agent_validator.py +2 -2
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/METADATA +1 -1
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/RECORD +96 -71
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/WHEEL +0 -0
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.3.20.dist-info → claude_mpm-4.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,298 @@
|
|
1
|
+
"""
|
2
|
+
Database Connector with Fallback Support
|
3
|
+
=========================================
|
4
|
+
|
5
|
+
WHY: Database connectivity packages often have compilation requirements that
|
6
|
+
can fail on certain systems. This module provides intelligent fallback to
|
7
|
+
pure Python alternatives when native packages are unavailable.
|
8
|
+
|
9
|
+
DESIGN DECISION: We prioritize pure Python implementations over native ones
|
10
|
+
for better cross-platform compatibility, even if they might be slightly slower.
|
11
|
+
"""
|
12
|
+
|
13
|
+
import logging
|
14
|
+
from typing import Any, Dict, Optional, Tuple
|
15
|
+
|
16
|
+
from ..core.logger import get_logger
|
17
|
+
|
18
|
+
logger = get_logger(__name__)
|
19
|
+
|
20
|
+
|
21
|
+
class DatabaseConnector:
|
22
|
+
"""
|
23
|
+
Manages database connections with automatic fallback to alternative drivers.
|
24
|
+
|
25
|
+
WHY: Provides a unified interface for database connections that automatically
|
26
|
+
handles missing or failed driver installations by falling back to alternatives.
|
27
|
+
"""
|
28
|
+
|
29
|
+
# Database drivers in order of preference (first is preferred)
|
30
|
+
MYSQL_DRIVERS = [
|
31
|
+
("pymysql", "pymysql"), # Pure Python, no compilation required
|
32
|
+
("mysqlclient", "MySQLdb"), # Faster but requires MySQL dev headers
|
33
|
+
("mysql-connector-python", "mysql.connector"), # Oracle's pure Python driver
|
34
|
+
]
|
35
|
+
|
36
|
+
POSTGRESQL_DRIVERS = [
|
37
|
+
("psycopg2-binary", "psycopg2"), # Binary wheel, no compilation
|
38
|
+
("psycopg2", "psycopg2"), # Requires PostgreSQL dev headers
|
39
|
+
("pg8000", "pg8000"), # Pure Python alternative
|
40
|
+
]
|
41
|
+
|
42
|
+
ORACLE_DRIVERS = [
|
43
|
+
("cx_Oracle", "cx_Oracle"), # Requires Oracle client libraries
|
44
|
+
("oracledb", "oracledb"), # Pure Python Oracle driver (newer)
|
45
|
+
]
|
46
|
+
|
47
|
+
def __init__(self):
|
48
|
+
"""Initialize the database connector."""
|
49
|
+
self.available_drivers: Dict[str, Tuple[str, Any]] = {}
|
50
|
+
self._scan_available_drivers()
|
51
|
+
|
52
|
+
def _scan_available_drivers(self) -> None:
|
53
|
+
"""
|
54
|
+
Scan for available database drivers and cache them.
|
55
|
+
|
56
|
+
WHY: Pre-scanning allows us to know what's available without
|
57
|
+
repeatedly trying imports, improving performance.
|
58
|
+
"""
|
59
|
+
# Check MySQL drivers
|
60
|
+
for package_name, import_name in self.MYSQL_DRIVERS:
|
61
|
+
driver = self._try_import(import_name)
|
62
|
+
if driver:
|
63
|
+
if "mysql" not in self.available_drivers:
|
64
|
+
self.available_drivers["mysql"] = (package_name, driver)
|
65
|
+
logger.info(f"MySQL driver available: {package_name}")
|
66
|
+
|
67
|
+
# Check PostgreSQL drivers
|
68
|
+
for package_name, import_name in self.POSTGRESQL_DRIVERS:
|
69
|
+
driver = self._try_import(import_name)
|
70
|
+
if driver:
|
71
|
+
if "postgresql" not in self.available_drivers:
|
72
|
+
self.available_drivers["postgresql"] = (package_name, driver)
|
73
|
+
logger.info(f"PostgreSQL driver available: {package_name}")
|
74
|
+
|
75
|
+
# Check Oracle drivers
|
76
|
+
for package_name, import_name in self.ORACLE_DRIVERS:
|
77
|
+
driver = self._try_import(import_name)
|
78
|
+
if driver:
|
79
|
+
if "oracle" not in self.available_drivers:
|
80
|
+
self.available_drivers["oracle"] = (package_name, driver)
|
81
|
+
logger.info(f"Oracle driver available: {package_name}")
|
82
|
+
|
83
|
+
def _try_import(self, module_name: str) -> Optional[Any]:
|
84
|
+
"""
|
85
|
+
Try to import a module and return it if successful.
|
86
|
+
|
87
|
+
Args:
|
88
|
+
module_name: Name of the module to import
|
89
|
+
|
90
|
+
Returns:
|
91
|
+
The imported module or None if import fails
|
92
|
+
"""
|
93
|
+
try:
|
94
|
+
import importlib
|
95
|
+
return importlib.import_module(module_name)
|
96
|
+
except ImportError:
|
97
|
+
return None
|
98
|
+
|
99
|
+
def get_mysql_connection_string(self, host: str, database: str, user: str,
|
100
|
+
password: str, port: int = 3306) -> Optional[str]:
|
101
|
+
"""
|
102
|
+
Get a SQLAlchemy connection string for MySQL with automatic driver selection.
|
103
|
+
|
104
|
+
WHY: SQLAlchemy needs different connection string formats depending on the driver.
|
105
|
+
This method automatically selects the best available driver.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
host: Database host
|
109
|
+
database: Database name
|
110
|
+
user: Username
|
111
|
+
password: Password
|
112
|
+
port: Port number (default 3306)
|
113
|
+
|
114
|
+
Returns:
|
115
|
+
SQLAlchemy connection string or None if no driver available
|
116
|
+
"""
|
117
|
+
if "mysql" not in self.available_drivers:
|
118
|
+
logger.error(
|
119
|
+
"No MySQL driver available. Install one of: pymysql, mysqlclient, or mysql-connector-python"
|
120
|
+
)
|
121
|
+
return None
|
122
|
+
|
123
|
+
package_name, _ = self.available_drivers["mysql"]
|
124
|
+
|
125
|
+
# Format connection string based on driver
|
126
|
+
if package_name == "pymysql":
|
127
|
+
return f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}"
|
128
|
+
elif package_name == "mysqlclient":
|
129
|
+
return f"mysql+mysqldb://{user}:{password}@{host}:{port}/{database}"
|
130
|
+
elif package_name == "mysql-connector-python":
|
131
|
+
return f"mysql+mysqlconnector://{user}:{password}@{host}:{port}/{database}"
|
132
|
+
|
133
|
+
return None
|
134
|
+
|
135
|
+
def get_postgresql_connection_string(self, host: str, database: str, user: str,
|
136
|
+
password: str, port: int = 5432) -> Optional[str]:
|
137
|
+
"""
|
138
|
+
Get a SQLAlchemy connection string for PostgreSQL with automatic driver selection.
|
139
|
+
|
140
|
+
Args:
|
141
|
+
host: Database host
|
142
|
+
database: Database name
|
143
|
+
user: Username
|
144
|
+
password: Password
|
145
|
+
port: Port number (default 5432)
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
SQLAlchemy connection string or None if no driver available
|
149
|
+
"""
|
150
|
+
if "postgresql" not in self.available_drivers:
|
151
|
+
logger.error(
|
152
|
+
"No PostgreSQL driver available. Install one of: psycopg2-binary, psycopg2, or pg8000"
|
153
|
+
)
|
154
|
+
return None
|
155
|
+
|
156
|
+
package_name, _ = self.available_drivers["postgresql"]
|
157
|
+
|
158
|
+
# Format connection string based on driver
|
159
|
+
if package_name in ["psycopg2-binary", "psycopg2"]:
|
160
|
+
return f"postgresql+psycopg2://{user}:{password}@{host}:{port}/{database}"
|
161
|
+
elif package_name == "pg8000":
|
162
|
+
return f"postgresql+pg8000://{user}:{password}@{host}:{port}/{database}"
|
163
|
+
|
164
|
+
return None
|
165
|
+
|
166
|
+
def get_oracle_connection_string(self, host: str, database: str, user: str,
|
167
|
+
password: str, port: int = 1521) -> Optional[str]:
|
168
|
+
"""
|
169
|
+
Get a SQLAlchemy connection string for Oracle with automatic driver selection.
|
170
|
+
|
171
|
+
Args:
|
172
|
+
host: Database host
|
173
|
+
database: Database name/SID
|
174
|
+
user: Username
|
175
|
+
password: Password
|
176
|
+
port: Port number (default 1521)
|
177
|
+
|
178
|
+
Returns:
|
179
|
+
SQLAlchemy connection string or None if no driver available
|
180
|
+
"""
|
181
|
+
if "oracle" not in self.available_drivers:
|
182
|
+
logger.error(
|
183
|
+
"No Oracle driver available. Install one of: cx_Oracle or oracledb"
|
184
|
+
)
|
185
|
+
return None
|
186
|
+
|
187
|
+
package_name, _ = self.available_drivers["oracle"]
|
188
|
+
|
189
|
+
# Format connection string based on driver
|
190
|
+
if package_name == "cx_Oracle":
|
191
|
+
return f"oracle+cx_oracle://{user}:{password}@{host}:{port}/{database}"
|
192
|
+
elif package_name == "oracledb":
|
193
|
+
return f"oracle+oracledb://{user}:{password}@{host}:{port}/{database}"
|
194
|
+
|
195
|
+
return None
|
196
|
+
|
197
|
+
def get_available_drivers(self) -> Dict[str, str]:
|
198
|
+
"""
|
199
|
+
Get a summary of available database drivers.
|
200
|
+
|
201
|
+
Returns:
|
202
|
+
Dictionary mapping database type to driver package name
|
203
|
+
"""
|
204
|
+
return {
|
205
|
+
db_type: driver_info[0]
|
206
|
+
for db_type, driver_info in self.available_drivers.items()
|
207
|
+
}
|
208
|
+
|
209
|
+
def suggest_missing_drivers(self) -> Dict[str, str]:
|
210
|
+
"""
|
211
|
+
Suggest drivers to install for databases without drivers.
|
212
|
+
|
213
|
+
Returns:
|
214
|
+
Dictionary mapping database type to recommended package
|
215
|
+
"""
|
216
|
+
suggestions = {}
|
217
|
+
|
218
|
+
if "mysql" not in self.available_drivers:
|
219
|
+
suggestions["mysql"] = "pymysql" # Pure Python, always works
|
220
|
+
|
221
|
+
if "postgresql" not in self.available_drivers:
|
222
|
+
suggestions["postgresql"] = "psycopg2-binary" # No compilation needed
|
223
|
+
|
224
|
+
if "oracle" not in self.available_drivers:
|
225
|
+
suggestions["oracle"] = "oracledb" # Pure Python, newer
|
226
|
+
|
227
|
+
return suggestions
|
228
|
+
|
229
|
+
@staticmethod
|
230
|
+
def get_installation_help() -> str:
|
231
|
+
"""
|
232
|
+
Get helpful installation instructions for database drivers.
|
233
|
+
|
234
|
+
Returns:
|
235
|
+
Formatted help text
|
236
|
+
"""
|
237
|
+
return """
|
238
|
+
Database Driver Installation Help
|
239
|
+
=================================
|
240
|
+
|
241
|
+
For MySQL:
|
242
|
+
Recommended: pip install pymysql (pure Python, no compilation)
|
243
|
+
Alternative: pip install mysql-connector-python (Oracle's pure Python)
|
244
|
+
Fastest (requires MySQL dev headers):
|
245
|
+
macOS: brew install mysql && pip install mysqlclient
|
246
|
+
Ubuntu: sudo apt-get install libmysqlclient-dev && pip install mysqlclient
|
247
|
+
|
248
|
+
For PostgreSQL:
|
249
|
+
Recommended: pip install psycopg2-binary (pre-compiled, no headers needed)
|
250
|
+
Alternative: pip install pg8000 (pure Python, slightly slower)
|
251
|
+
Fastest (requires PostgreSQL dev headers):
|
252
|
+
macOS: brew install postgresql && pip install psycopg2
|
253
|
+
Ubuntu: sudo apt-get install libpq-dev && pip install psycopg2
|
254
|
+
|
255
|
+
For Oracle:
|
256
|
+
Recommended: pip install oracledb (pure Python, no Oracle client needed)
|
257
|
+
Alternative (requires Oracle Instant Client):
|
258
|
+
1. Download Oracle Instant Client from oracle.com
|
259
|
+
2. Set environment variables (LD_LIBRARY_PATH, etc.)
|
260
|
+
3. pip install cx_Oracle
|
261
|
+
|
262
|
+
Note: Pure Python drivers are slightly slower but much easier to install
|
263
|
+
and maintain. They're recommended unless you have specific performance needs.
|
264
|
+
"""
|
265
|
+
|
266
|
+
|
267
|
+
def test_database_connectivity() -> None:
|
268
|
+
"""
|
269
|
+
Test database connectivity and report available drivers.
|
270
|
+
|
271
|
+
WHY: Helps users understand what database drivers are available and
|
272
|
+
what they might need to install.
|
273
|
+
"""
|
274
|
+
connector = DatabaseConnector()
|
275
|
+
|
276
|
+
print("Database Driver Status")
|
277
|
+
print("=" * 50)
|
278
|
+
|
279
|
+
available = connector.get_available_drivers()
|
280
|
+
if available:
|
281
|
+
print("\nAvailable Drivers:")
|
282
|
+
for db_type, driver in available.items():
|
283
|
+
print(f" {db_type:12} -> {driver}")
|
284
|
+
else:
|
285
|
+
print("\nNo database drivers found!")
|
286
|
+
|
287
|
+
suggestions = connector.suggest_missing_drivers()
|
288
|
+
if suggestions:
|
289
|
+
print("\nRecommended installations for missing drivers:")
|
290
|
+
for db_type, package in suggestions.items():
|
291
|
+
print(f" {db_type:12} -> pip install {package}")
|
292
|
+
|
293
|
+
print("\n" + connector.get_installation_help())
|
294
|
+
|
295
|
+
|
296
|
+
if __name__ == "__main__":
|
297
|
+
# Run connectivity test when module is executed directly
|
298
|
+
test_database_connectivity()
|
@@ -10,7 +10,8 @@ from datetime import datetime, timezone
|
|
10
10
|
from functools import wraps
|
11
11
|
from typing import Any, Callable, Dict, List, Optional, Type
|
12
12
|
|
13
|
-
|
13
|
+
from claude_mpm.core.logging_utils import get_logger
|
14
|
+
logger = get_logger(__name__)
|
14
15
|
|
15
16
|
|
16
17
|
class MPMError(Exception):
|
claude_mpm/utils/log_cleanup.py
CHANGED
@@ -6,14 +6,14 @@ including session directory cleanup, archived log removal, and rotation manageme
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
import gzip
|
9
|
-
import logging
|
10
9
|
import os
|
11
10
|
import shutil
|
12
11
|
from datetime import datetime, timedelta, timezone
|
13
12
|
from pathlib import Path
|
14
13
|
from typing import Dict, Optional, Tuple
|
15
14
|
|
16
|
-
|
15
|
+
from claude_mpm.core.logging_utils import get_logger
|
16
|
+
logger = get_logger(__name__)
|
17
17
|
|
18
18
|
|
19
19
|
class LogCleanupConfig:
|
@@ -4,14 +4,14 @@ This module provides a centralized PathOperations class for common path validati
|
|
4
4
|
and file operations, reducing code duplication across the codebase.
|
5
5
|
"""
|
6
6
|
|
7
|
-
import logging
|
8
7
|
import os
|
9
8
|
import shutil
|
10
9
|
import tempfile
|
11
10
|
from pathlib import Path
|
12
11
|
from typing import Callable, List, Optional, Union
|
13
12
|
|
14
|
-
|
13
|
+
from claude_mpm.core.logging_utils import get_logger
|
14
|
+
logger = get_logger(__name__)
|
15
15
|
|
16
16
|
|
17
17
|
class PathOperations:
|
@@ -340,6 +340,12 @@ class RobustPackageInstaller:
|
|
340
340
|
"tree-sitter-java",
|
341
341
|
"tree-sitter-cpp",
|
342
342
|
"tree-sitter-c",
|
343
|
+
# Database packages that require compilation
|
344
|
+
"mysqlclient", # Requires MySQL development headers
|
345
|
+
"psycopg2", # Requires PostgreSQL development headers
|
346
|
+
"cx_oracle", # Requires Oracle client libraries
|
347
|
+
"pycairo", # Requires Cairo development headers
|
348
|
+
"lxml", # Requires libxml2 development headers
|
343
349
|
}
|
344
350
|
|
345
351
|
return package_name.lower() in special_packages
|
@@ -363,6 +369,35 @@ class RobustPackageInstaller:
|
|
363
369
|
InstallStrategy.PIP_NO_DEPS,
|
364
370
|
]
|
365
371
|
|
372
|
+
# Database packages that require compilation
|
373
|
+
compilation_packages = {
|
374
|
+
"mysqlclient": ["pymysql"], # Pure Python alternative
|
375
|
+
"psycopg2": ["psycopg2-binary"], # Binary wheel alternative
|
376
|
+
"cx_oracle": [], # No good alternative
|
377
|
+
"pycairo": [], # No good alternative
|
378
|
+
"lxml": [], # Usually works with binary wheels
|
379
|
+
}
|
380
|
+
|
381
|
+
package_lower = package_name.lower()
|
382
|
+
if package_lower in compilation_packages:
|
383
|
+
# Try normal install first, but with limited retries
|
384
|
+
strategies = [InstallStrategy.PIP]
|
385
|
+
|
386
|
+
# If there are alternatives, log suggestion
|
387
|
+
alternatives = compilation_packages[package_lower]
|
388
|
+
if alternatives:
|
389
|
+
logger.info(
|
390
|
+
f"Package {package_name} requires compilation. "
|
391
|
+
f"Consider using alternative: {', '.join(alternatives)}"
|
392
|
+
)
|
393
|
+
else:
|
394
|
+
logger.warning(
|
395
|
+
f"Package {package_name} requires compilation and may fail on systems "
|
396
|
+
f"without development headers installed."
|
397
|
+
)
|
398
|
+
|
399
|
+
return strategies
|
400
|
+
|
366
401
|
return [InstallStrategy.PIP, InstallStrategy.PIP_UPGRADE]
|
367
402
|
|
368
403
|
def _verify_installation(self, package_spec: str) -> bool:
|
@@ -459,6 +494,27 @@ class RobustPackageInstaller:
|
|
459
494
|
if not stderr:
|
460
495
|
return "Unknown error"
|
461
496
|
|
497
|
+
# Check for specific compilation errors
|
498
|
+
stderr_lower = stderr.lower()
|
499
|
+
|
500
|
+
if "mysql_config" in stderr_lower or "mysql.h" in stderr_lower:
|
501
|
+
return (
|
502
|
+
"mysqlclient compilation failed (missing MySQL development headers). "
|
503
|
+
"Use 'pip install pymysql' for a pure Python alternative that doesn't require compilation."
|
504
|
+
)
|
505
|
+
|
506
|
+
if "pg_config" in stderr_lower or "libpq-fe.h" in stderr_lower:
|
507
|
+
return (
|
508
|
+
"psycopg2 compilation failed (missing PostgreSQL development headers). "
|
509
|
+
"Use 'pip install psycopg2-binary' for a pre-compiled version."
|
510
|
+
)
|
511
|
+
|
512
|
+
if "oracle" in stderr_lower and "client" in stderr_lower:
|
513
|
+
return (
|
514
|
+
"cx_Oracle compilation failed (missing Oracle client libraries). "
|
515
|
+
"Use 'pip install oracledb' for a pure Python alternative."
|
516
|
+
)
|
517
|
+
|
462
518
|
# Look for ERROR: lines
|
463
519
|
error_lines = []
|
464
520
|
for line in stderr.splitlines():
|
@@ -6,13 +6,13 @@ Session Logging Utilities
|
|
6
6
|
Convenience functions for session-based response logging.
|
7
7
|
"""
|
8
8
|
|
9
|
-
import logging
|
10
9
|
import os
|
11
10
|
from typing import Any, Dict, Optional
|
12
11
|
|
13
12
|
from claude_mpm.services.claude_session_logger import get_session_logger
|
14
13
|
|
15
|
-
|
14
|
+
from claude_mpm.core.logging_utils import get_logger
|
15
|
+
logger = get_logger(__name__)
|
16
16
|
|
17
17
|
|
18
18
|
def is_session_logging_enabled() -> bool:
|
@@ -8,7 +8,6 @@ with proper error handling, timeouts, and process cleanup.
|
|
8
8
|
|
9
9
|
import asyncio
|
10
10
|
import contextlib
|
11
|
-
import logging
|
12
11
|
import shlex
|
13
12
|
import subprocess
|
14
13
|
import time
|
@@ -16,7 +15,8 @@ from typing import Any, Dict, List, Optional
|
|
16
15
|
|
17
16
|
import psutil
|
18
17
|
|
19
|
-
|
18
|
+
from claude_mpm.core.logging_utils import get_logger
|
19
|
+
logger = get_logger(__name__)
|
20
20
|
|
21
21
|
|
22
22
|
class SubprocessError(Exception):
|
@@ -20,7 +20,6 @@ Security Considerations:
|
|
20
20
|
"""
|
21
21
|
|
22
22
|
import json
|
23
|
-
import logging
|
24
23
|
from dataclasses import dataclass, field
|
25
24
|
from datetime import datetime, timezone
|
26
25
|
from pathlib import Path
|
@@ -36,7 +35,8 @@ from claude_mpm.core.constants import (
|
|
36
35
|
TimeoutConfig,
|
37
36
|
)
|
38
37
|
|
39
|
-
|
38
|
+
from claude_mpm.core.logging_utils import get_logger
|
39
|
+
logger = get_logger(__name__)
|
40
40
|
|
41
41
|
|
42
42
|
@dataclass
|