claude-mpm 4.5.11__py3-none-any.whl → 4.5.12__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/frontmatter_validator.py +4 -4
- claude_mpm/cli/commands/agent_manager.py +3 -3
- claude_mpm/cli/commands/agents.py +6 -6
- claude_mpm/cli/commands/aggregate.py +4 -4
- claude_mpm/cli/commands/analyze.py +2 -2
- claude_mpm/cli/commands/analyze_code.py +1 -1
- claude_mpm/cli/commands/cleanup.py +3 -3
- claude_mpm/cli/commands/config.py +2 -2
- claude_mpm/cli/commands/configure.py +14 -14
- claude_mpm/cli/commands/dashboard.py +1 -1
- claude_mpm/cli/commands/debug.py +3 -3
- claude_mpm/cli/commands/doctor.py +1 -1
- claude_mpm/cli/commands/mcp.py +7 -7
- claude_mpm/cli/commands/mcp_command_router.py +1 -1
- claude_mpm/cli/commands/mcp_config.py +2 -2
- claude_mpm/cli/commands/mcp_external_commands.py +2 -2
- claude_mpm/cli/commands/mcp_install_commands.py +3 -3
- claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
- claude_mpm/cli/commands/mcp_setup_external.py +3 -3
- claude_mpm/cli/commands/monitor.py +1 -1
- claude_mpm/cli/commands/mpm_init_handler.py +1 -1
- claude_mpm/cli/interactive/agent_wizard.py +1 -1
- claude_mpm/cli/parsers/search_parser.py +1 -1
- claude_mpm/cli/shared/argument_patterns.py +2 -2
- claude_mpm/cli/shared/base_command.py +1 -1
- claude_mpm/cli/startup_logging.py +4 -4
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/socketio_config.py +2 -2
- claude_mpm/core/agent_session_manager.py +2 -2
- claude_mpm/core/api_validator.py +3 -3
- claude_mpm/core/base_service.py +10 -1
- claude_mpm/core/cache.py +2 -2
- claude_mpm/core/config.py +4 -4
- claude_mpm/core/config_aliases.py +4 -4
- claude_mpm/core/config_constants.py +1 -1
- claude_mpm/core/error_handler.py +1 -1
- claude_mpm/core/file_utils.py +5 -5
- claude_mpm/core/framework/formatters/capability_generator.py +5 -5
- claude_mpm/core/framework/loaders/agent_loader.py +1 -1
- claude_mpm/core/framework/processors/metadata_processor.py +1 -1
- claude_mpm/core/framework/processors/template_processor.py +3 -3
- claude_mpm/core/framework_loader.py +2 -2
- claude_mpm/core/log_manager.py +4 -4
- claude_mpm/core/logger.py +2 -2
- claude_mpm/core/optimized_startup.py +1 -1
- claude_mpm/core/output_style_manager.py +1 -1
- claude_mpm/core/service_registry.py +2 -2
- claude_mpm/core/session_manager.py +3 -3
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/socketio_pool.py +2 -2
- claude_mpm/core/unified_agent_registry.py +2 -2
- claude_mpm/core/unified_config.py +6 -6
- claude_mpm/core/unified_paths.py +2 -2
- claude_mpm/dashboard/api/simple_directory.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +1 -1
- claude_mpm/hooks/claude_hooks/event_handlers.py +2 -2
- claude_mpm/hooks/claude_hooks/installer.py +9 -9
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +7 -2
- claude_mpm/hooks/claude_hooks/tool_analysis.py +2 -2
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/hooks/validation_hooks.py +1 -1
- claude_mpm/init.py +4 -4
- claude_mpm/models/agent_session.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +5 -5
- claude_mpm/services/__init__.py +2 -2
- claude_mpm/services/agent_capabilities_service.py +1 -1
- claude_mpm/services/agents/agent_builder.py +4 -4
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +3 -3
- claude_mpm/services/agents/deployment/deployment_wrapper.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +2 -2
- claude_mpm/services/agents/local_template_manager.py +5 -5
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +1 -1
- claude_mpm/services/agents/registry/modification_tracker.py +19 -11
- claude_mpm/services/async_session_logger.py +1 -1
- claude_mpm/services/claude_session_logger.py +1 -1
- claude_mpm/services/cli/agent_listing_service.py +3 -3
- claude_mpm/services/cli/agent_validation_service.py +1 -1
- claude_mpm/services/cli/session_manager.py +2 -2
- claude_mpm/services/core/path_resolver.py +1 -1
- claude_mpm/services/diagnostics/checks/agent_check.py +1 -1
- claude_mpm/services/diagnostics/checks/claude_code_check.py +2 -2
- claude_mpm/services/diagnostics/checks/common_issues_check.py +3 -3
- claude_mpm/services/diagnostics/checks/configuration_check.py +2 -2
- claude_mpm/services/diagnostics/checks/installation_check.py +1 -1
- claude_mpm/services/diagnostics/checks/mcp_check.py +1 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +9 -9
- claude_mpm/services/diagnostics/checks/monitor_check.py +1 -1
- claude_mpm/services/diagnostics/doctor_reporter.py +1 -1
- claude_mpm/services/event_aggregator.py +1 -1
- claude_mpm/services/event_bus/event_bus.py +7 -2
- claude_mpm/services/events/consumers/dead_letter.py +2 -2
- claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
- claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
- claude_mpm/services/hook_installer_service.py +7 -7
- claude_mpm/services/infrastructure/context_preservation.py +7 -7
- claude_mpm/services/infrastructure/daemon_manager.py +5 -5
- claude_mpm/services/mcp_config_manager.py +10 -10
- claude_mpm/services/mcp_gateway/auto_configure.py +5 -5
- claude_mpm/services/mcp_gateway/config/config_loader.py +2 -2
- claude_mpm/services/mcp_gateway/config/configuration.py +3 -3
- claude_mpm/services/mcp_gateway/core/process_pool.py +3 -3
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
- claude_mpm/services/mcp_gateway/core/startup_verification.py +1 -1
- claude_mpm/services/mcp_gateway/main.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +2 -1
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +1 -1
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +1 -1
- claude_mpm/services/mcp_gateway/tools/hello_world.py +1 -1
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +5 -5
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +2 -2
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/builder.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
- claude_mpm/services/memory/indexed_memory.py +3 -3
- claude_mpm/services/monitor/daemon.py +1 -1
- claude_mpm/services/monitor/daemon_manager.py +9 -9
- claude_mpm/services/monitor/handlers/file.py +1 -1
- claude_mpm/services/monitor/handlers/hooks.py +3 -3
- claude_mpm/services/monitor/management/lifecycle.py +7 -7
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/orphan_detection.py +13 -16
- claude_mpm/services/port_manager.py +2 -2
- claude_mpm/services/project/analyzer.py +3 -3
- claude_mpm/services/project/archive_manager.py +13 -13
- claude_mpm/services/project/dependency_analyzer.py +4 -4
- claude_mpm/services/project/documentation_manager.py +4 -4
- claude_mpm/services/project/enhanced_analyzer.py +8 -8
- claude_mpm/services/project/registry.py +4 -4
- claude_mpm/services/project_port_allocator.py +7 -11
- claude_mpm/services/session_management_service.py +1 -1
- claude_mpm/services/socketio/event_normalizer.py +1 -1
- claude_mpm/services/socketio/handlers/code_analysis.py +14 -12
- claude_mpm/services/socketio/handlers/file.py +1 -1
- claude_mpm/services/socketio/migration_utils.py +1 -1
- claude_mpm/services/socketio/server/core.py +1 -1
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +1 -1
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +4 -4
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +1 -1
- claude_mpm/services/unified/config_strategies/config_schema.py +4 -4
- claude_mpm/services/unified/config_strategies/context_strategy.py +6 -6
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +10 -10
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +5 -5
- claude_mpm/services/unified/config_strategies/unified_config_service.py +8 -8
- claude_mpm/services/unified/config_strategies/validation_strategy.py +15 -15
- claude_mpm/services/unified/deployment_strategies/base.py +4 -4
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +15 -15
- claude_mpm/services/unified/deployment_strategies/local.py +9 -9
- claude_mpm/services/unified/deployment_strategies/utils.py +9 -9
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -7
- claude_mpm/services/unified/unified_config.py +5 -5
- claude_mpm/services/unified/unified_deployment.py +2 -2
- claude_mpm/services/utility_service.py +1 -1
- claude_mpm/services/version_control/conflict_resolution.py +2 -2
- claude_mpm/services/version_control/git_operations.py +3 -3
- claude_mpm/services/version_control/semantic_versioning.py +13 -13
- claude_mpm/services/version_control/version_parser.py +1 -1
- claude_mpm/storage/state_storage.py +12 -13
- claude_mpm/tools/code_tree_analyzer.py +5 -5
- claude_mpm/tools/code_tree_builder.py +4 -4
- claude_mpm/tools/socketio_debug.py +1 -1
- claude_mpm/utils/agent_dependency_loader.py +4 -4
- claude_mpm/utils/common.py +2 -2
- claude_mpm/utils/config_manager.py +3 -3
- claude_mpm/utils/dependency_cache.py +2 -2
- claude_mpm/utils/dependency_strategies.py +6 -6
- claude_mpm/utils/file_utils.py +11 -11
- claude_mpm/utils/log_cleanup.py +1 -1
- claude_mpm/utils/path_operations.py +1 -1
- claude_mpm/validation/agent_validator.py +2 -2
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/METADATA +1 -1
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/RECORD +183 -183
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/WHEEL +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.12.dist-info}/top_level.txt +0 -0
|
@@ -12,7 +12,7 @@ import threading
|
|
|
12
12
|
from abc import ABC, abstractmethod
|
|
13
13
|
from collections import defaultdict
|
|
14
14
|
from dataclasses import dataclass, field
|
|
15
|
-
from datetime import datetime, timedelta
|
|
15
|
+
from datetime import datetime, timedelta, timezone
|
|
16
16
|
from enum import Enum
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Callable, Dict, List, Optional, TypeVar, Union
|
|
@@ -216,7 +216,7 @@ class UnifiedConfigService:
|
|
|
216
216
|
source=str(source),
|
|
217
217
|
format=format,
|
|
218
218
|
context=context,
|
|
219
|
-
loaded_at=datetime.now(),
|
|
219
|
+
loaded_at=datetime.now(timezone.utc),
|
|
220
220
|
checksum=self._calculate_checksum(config),
|
|
221
221
|
hot_reload=hot_reload,
|
|
222
222
|
ttl=ttl,
|
|
@@ -439,7 +439,7 @@ class UnifiedConfigService:
|
|
|
439
439
|
|
|
440
440
|
path = Path(source)
|
|
441
441
|
if path.exists():
|
|
442
|
-
with open(
|
|
442
|
+
with path.open() as f:
|
|
443
443
|
return json.load(f)
|
|
444
444
|
|
|
445
445
|
# Try to parse as JSON string
|
|
@@ -452,7 +452,7 @@ class UnifiedConfigService:
|
|
|
452
452
|
|
|
453
453
|
path = Path(source)
|
|
454
454
|
if path.exists():
|
|
455
|
-
with open(
|
|
455
|
+
with path.open() as f:
|
|
456
456
|
return yaml.safe_load(f)
|
|
457
457
|
|
|
458
458
|
# Try to parse as YAML string
|
|
@@ -476,7 +476,7 @@ class UnifiedConfigService:
|
|
|
476
476
|
# Try to parse value
|
|
477
477
|
try:
|
|
478
478
|
config[clean_key] = json.loads(value)
|
|
479
|
-
except:
|
|
479
|
+
except (json.JSONDecodeError, ValueError):
|
|
480
480
|
config[clean_key] = value
|
|
481
481
|
|
|
482
482
|
return config
|
|
@@ -508,7 +508,7 @@ class UnifiedConfigService:
|
|
|
508
508
|
|
|
509
509
|
path = Path(source)
|
|
510
510
|
if path.exists():
|
|
511
|
-
with open(
|
|
511
|
+
with path.open() as f:
|
|
512
512
|
return toml.load(f)
|
|
513
513
|
|
|
514
514
|
return toml.loads(str(source))
|
|
@@ -706,7 +706,7 @@ class UnifiedConfigService:
|
|
|
706
706
|
"""Check if cached configuration is still valid"""
|
|
707
707
|
if metadata.ttl:
|
|
708
708
|
expiry = metadata.loaded_at + metadata.ttl
|
|
709
|
-
if datetime.now() > expiry:
|
|
709
|
+
if datetime.now(timezone.utc) > expiry:
|
|
710
710
|
return False
|
|
711
711
|
return True
|
|
712
712
|
|
|
@@ -742,7 +742,7 @@ class UnifiedConfigService:
|
|
|
742
742
|
result = handler(error, source, context)
|
|
743
743
|
if result is not None:
|
|
744
744
|
return result
|
|
745
|
-
except:
|
|
745
|
+
except Exception:
|
|
746
746
|
continue
|
|
747
747
|
|
|
748
748
|
self.logger.error(f"Failed to load config from {source}: {error}")
|
|
@@ -402,7 +402,7 @@ class FormatValidator(BaseValidator):
|
|
|
402
402
|
try:
|
|
403
403
|
result = urllib.parse.urlparse(value)
|
|
404
404
|
return all([result.scheme, result.netloc])
|
|
405
|
-
except:
|
|
405
|
+
except (ValueError, AttributeError, TypeError):
|
|
406
406
|
return False
|
|
407
407
|
|
|
408
408
|
@staticmethod
|
|
@@ -410,7 +410,7 @@ class FormatValidator(BaseValidator):
|
|
|
410
410
|
try:
|
|
411
411
|
result = urllib.parse.urlparse(value)
|
|
412
412
|
return bool(result.scheme)
|
|
413
|
-
except:
|
|
413
|
+
except (ValueError, AttributeError, TypeError):
|
|
414
414
|
return False
|
|
415
415
|
|
|
416
416
|
@staticmethod
|
|
@@ -420,7 +420,7 @@ class FormatValidator(BaseValidator):
|
|
|
420
420
|
try:
|
|
421
421
|
uuid.UUID(value)
|
|
422
422
|
return True
|
|
423
|
-
except:
|
|
423
|
+
except (ValueError, AttributeError, TypeError):
|
|
424
424
|
return False
|
|
425
425
|
|
|
426
426
|
@staticmethod
|
|
@@ -428,7 +428,7 @@ class FormatValidator(BaseValidator):
|
|
|
428
428
|
try:
|
|
429
429
|
ipaddress.IPv4Address(value)
|
|
430
430
|
return True
|
|
431
|
-
except:
|
|
431
|
+
except (ValueError, ipaddress.AddressValueError):
|
|
432
432
|
return False
|
|
433
433
|
|
|
434
434
|
@staticmethod
|
|
@@ -436,7 +436,7 @@ class FormatValidator(BaseValidator):
|
|
|
436
436
|
try:
|
|
437
437
|
ipaddress.IPv6Address(value)
|
|
438
438
|
return True
|
|
439
|
-
except:
|
|
439
|
+
except (ValueError, ipaddress.AddressValueError):
|
|
440
440
|
return False
|
|
441
441
|
|
|
442
442
|
@staticmethod
|
|
@@ -444,7 +444,7 @@ class FormatValidator(BaseValidator):
|
|
|
444
444
|
try:
|
|
445
445
|
ipaddress.ip_address(value)
|
|
446
446
|
return True
|
|
447
|
-
except:
|
|
447
|
+
except (ValueError, ipaddress.AddressValueError):
|
|
448
448
|
return False
|
|
449
449
|
|
|
450
450
|
@staticmethod
|
|
@@ -461,7 +461,7 @@ class FormatValidator(BaseValidator):
|
|
|
461
461
|
try:
|
|
462
462
|
datetime.strptime(value, "%Y-%m-%d")
|
|
463
463
|
return True
|
|
464
|
-
except:
|
|
464
|
+
except (ValueError, TypeError):
|
|
465
465
|
return False
|
|
466
466
|
|
|
467
467
|
@staticmethod
|
|
@@ -469,11 +469,11 @@ class FormatValidator(BaseValidator):
|
|
|
469
469
|
try:
|
|
470
470
|
datetime.strptime(value, "%H:%M:%S")
|
|
471
471
|
return True
|
|
472
|
-
except:
|
|
472
|
+
except (ValueError, TypeError):
|
|
473
473
|
try:
|
|
474
474
|
datetime.strptime(value, "%H:%M")
|
|
475
475
|
return True
|
|
476
|
-
except:
|
|
476
|
+
except (ValueError, TypeError):
|
|
477
477
|
return False
|
|
478
478
|
|
|
479
479
|
@staticmethod
|
|
@@ -488,7 +488,7 @@ class FormatValidator(BaseValidator):
|
|
|
488
488
|
try:
|
|
489
489
|
datetime.strptime(value, fmt)
|
|
490
490
|
return True
|
|
491
|
-
except:
|
|
491
|
+
except (ValueError, TypeError):
|
|
492
492
|
continue
|
|
493
493
|
return False
|
|
494
494
|
|
|
@@ -499,7 +499,7 @@ class FormatValidator(BaseValidator):
|
|
|
499
499
|
try:
|
|
500
500
|
json.loads(value)
|
|
501
501
|
return True
|
|
502
|
-
except:
|
|
502
|
+
except (json.JSONDecodeError, ValueError, TypeError):
|
|
503
503
|
return False
|
|
504
504
|
|
|
505
505
|
@staticmethod
|
|
@@ -509,7 +509,7 @@ class FormatValidator(BaseValidator):
|
|
|
509
509
|
try:
|
|
510
510
|
base64.b64decode(value, validate=True)
|
|
511
511
|
return True
|
|
512
|
-
except:
|
|
512
|
+
except (ValueError, base64.binascii.Error):
|
|
513
513
|
return False
|
|
514
514
|
|
|
515
515
|
@staticmethod
|
|
@@ -517,7 +517,7 @@ class FormatValidator(BaseValidator):
|
|
|
517
517
|
try:
|
|
518
518
|
Path(value)
|
|
519
519
|
return True
|
|
520
|
-
except:
|
|
520
|
+
except (ValueError, TypeError, OSError):
|
|
521
521
|
return False
|
|
522
522
|
|
|
523
523
|
@staticmethod
|
|
@@ -709,7 +709,7 @@ class ConditionalValidator(BaseValidator):
|
|
|
709
709
|
|
|
710
710
|
try:
|
|
711
711
|
return comparator(actual, expected)
|
|
712
|
-
except:
|
|
712
|
+
except (TypeError, ValueError, AttributeError, KeyError):
|
|
713
713
|
return False
|
|
714
714
|
|
|
715
715
|
def _apply_rule(
|
|
@@ -910,7 +910,7 @@ class CrossFieldValidator(BaseValidator):
|
|
|
910
910
|
if comparator:
|
|
911
911
|
try:
|
|
912
912
|
return comparator(val1, val2)
|
|
913
|
-
except:
|
|
913
|
+
except (TypeError, ValueError, AttributeError, KeyError):
|
|
914
914
|
return False
|
|
915
915
|
|
|
916
916
|
return False
|
|
@@ -15,7 +15,7 @@ This module provides:
|
|
|
15
15
|
|
|
16
16
|
from abc import abstractmethod
|
|
17
17
|
from dataclasses import dataclass, field
|
|
18
|
-
from datetime import datetime
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
19
|
from enum import Enum
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
from typing import Any, Dict, List, Optional, Union
|
|
@@ -255,7 +255,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
|
|
|
255
255
|
result = DeploymentResult(
|
|
256
256
|
success=False,
|
|
257
257
|
status=DeploymentStatus.PENDING,
|
|
258
|
-
started_at=datetime.now(),
|
|
258
|
+
started_at=datetime.now(timezone.utc),
|
|
259
259
|
)
|
|
260
260
|
|
|
261
261
|
try:
|
|
@@ -334,7 +334,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
|
|
|
334
334
|
result.errors.append(f"Rollback failed: {rollback_error!s}")
|
|
335
335
|
|
|
336
336
|
finally:
|
|
337
|
-
result.completed_at = datetime.now()
|
|
337
|
+
result.completed_at = datetime.now(timezone.utc)
|
|
338
338
|
if result.started_at:
|
|
339
339
|
result.duration_seconds = (
|
|
340
340
|
result.completed_at - result.started_at
|
|
@@ -532,7 +532,7 @@ class DeploymentStrategy(BaseDeploymentStrategy):
|
|
|
532
532
|
return {
|
|
533
533
|
"deployment_id": deployment_info.get("deployment_id"),
|
|
534
534
|
"deployed_path": str(deployment_info.get("deployed_path")),
|
|
535
|
-
"timestamp": datetime.now().isoformat(),
|
|
535
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
536
536
|
"artifacts": deployment_info.get("artifacts", []),
|
|
537
537
|
}
|
|
538
538
|
|
|
@@ -8,7 +8,7 @@ Reduces duplication by sharing common cloud deployment patterns.
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
import subprocess
|
|
11
|
-
from datetime import datetime
|
|
11
|
+
from datetime import datetime, timezone
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Any, Dict, List
|
|
14
14
|
|
|
@@ -48,7 +48,7 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
|
|
|
48
48
|
# Check Railway CLI
|
|
49
49
|
try:
|
|
50
50
|
subprocess.run(["railway", "--version"], capture_output=True, check=True)
|
|
51
|
-
except:
|
|
51
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
52
52
|
errors.append(
|
|
53
53
|
"Railway CLI not installed. Install with: npm i -g @railway/cli"
|
|
54
54
|
)
|
|
@@ -56,7 +56,7 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
|
|
|
56
56
|
# Check authentication
|
|
57
57
|
try:
|
|
58
58
|
subprocess.run(["railway", "whoami"], capture_output=True, check=True)
|
|
59
|
-
except:
|
|
59
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
60
60
|
errors.append("Not authenticated with Railway. Run: railway login")
|
|
61
61
|
|
|
62
62
|
return errors
|
|
@@ -97,13 +97,13 @@ class RailwayDeploymentStrategy(DeploymentStrategy):
|
|
|
97
97
|
break
|
|
98
98
|
|
|
99
99
|
return {
|
|
100
|
-
"deployment_id": f"railway_{datetime.now().timestamp()}",
|
|
100
|
+
"deployment_id": f"railway_{datetime.now(timezone.utc).timestamp()}",
|
|
101
101
|
"deployment_url": deployment_url,
|
|
102
102
|
"deployed_path": deploy_dir,
|
|
103
103
|
"stdout": result.stdout,
|
|
104
104
|
}
|
|
105
105
|
except subprocess.CalledProcessError as e:
|
|
106
|
-
raise Exception(f"Railway deployment failed: {e.stderr}")
|
|
106
|
+
raise Exception(f"Railway deployment failed: {e.stderr}") from e
|
|
107
107
|
|
|
108
108
|
def verify(
|
|
109
109
|
self, context: DeploymentContext, deployment_info: Dict[str, Any]
|
|
@@ -150,7 +150,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
|
|
|
150
150
|
# Check AWS CLI
|
|
151
151
|
try:
|
|
152
152
|
subprocess.run(["aws", "--version"], capture_output=True, check=True)
|
|
153
|
-
except:
|
|
153
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
154
154
|
errors.append("AWS CLI not installed")
|
|
155
155
|
|
|
156
156
|
# Check credentials
|
|
@@ -158,7 +158,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
|
|
|
158
158
|
subprocess.run(
|
|
159
159
|
["aws", "sts", "get-caller-identity"], capture_output=True, check=True
|
|
160
160
|
)
|
|
161
|
-
except:
|
|
161
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
162
162
|
errors.append("AWS credentials not configured")
|
|
163
163
|
|
|
164
164
|
# Validate service type
|
|
@@ -218,7 +218,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
|
|
|
218
218
|
"--zip-file",
|
|
219
219
|
f"fileb://{artifact}",
|
|
220
220
|
]
|
|
221
|
-
except:
|
|
221
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
222
222
|
# Create new function
|
|
223
223
|
cmd = [
|
|
224
224
|
"aws",
|
|
@@ -277,7 +277,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
|
|
|
277
277
|
]
|
|
278
278
|
subprocess.run(cmd, capture_output=True, check=True)
|
|
279
279
|
return True
|
|
280
|
-
except:
|
|
280
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
281
281
|
return False
|
|
282
282
|
|
|
283
283
|
return True
|
|
@@ -301,7 +301,7 @@ class AWSDeploymentStrategy(DeploymentStrategy):
|
|
|
301
301
|
try:
|
|
302
302
|
subprocess.run(cmd, check=True)
|
|
303
303
|
return True
|
|
304
|
-
except:
|
|
304
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
305
305
|
pass
|
|
306
306
|
return False
|
|
307
307
|
|
|
@@ -334,7 +334,7 @@ class DockerDeploymentStrategy(DeploymentStrategy):
|
|
|
334
334
|
# Check Docker
|
|
335
335
|
try:
|
|
336
336
|
subprocess.run(["docker", "--version"], capture_output=True, check=True)
|
|
337
|
-
except:
|
|
337
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
338
338
|
errors.append("Docker not installed or not running")
|
|
339
339
|
|
|
340
340
|
# Check Dockerfile exists
|
|
@@ -356,7 +356,7 @@ class DockerDeploymentStrategy(DeploymentStrategy):
|
|
|
356
356
|
"""Execute Docker deployment."""
|
|
357
357
|
source_dir = artifacts[0] if artifacts[0].is_dir() else artifacts[0].parent
|
|
358
358
|
image_name = context.config.get(
|
|
359
|
-
"image_name", f"app_{datetime.now().timestamp()}"
|
|
359
|
+
"image_name", f"app_{datetime.now(timezone.utc).timestamp()}"
|
|
360
360
|
)
|
|
361
361
|
container_name = context.config.get("container_name", image_name)
|
|
362
362
|
|
|
@@ -444,7 +444,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
|
|
|
444
444
|
# Check Git
|
|
445
445
|
try:
|
|
446
446
|
subprocess.run(["git", "--version"], capture_output=True, check=True)
|
|
447
|
-
except:
|
|
447
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
448
448
|
errors.append("Git not installed")
|
|
449
449
|
|
|
450
450
|
# Check remote URL
|
|
@@ -529,7 +529,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
|
|
|
529
529
|
check=True,
|
|
530
530
|
)
|
|
531
531
|
return True
|
|
532
|
-
except:
|
|
532
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
533
533
|
return False
|
|
534
534
|
|
|
535
535
|
def rollback(self, context: DeploymentContext, result: DeploymentResult) -> bool:
|
|
@@ -553,7 +553,7 @@ class GitDeploymentStrategy(DeploymentStrategy):
|
|
|
553
553
|
check=True,
|
|
554
554
|
)
|
|
555
555
|
return True
|
|
556
|
-
except:
|
|
556
|
+
except (subprocess.CalledProcessError, FileNotFoundError, OSError):
|
|
557
557
|
pass
|
|
558
558
|
return False
|
|
559
559
|
|
|
@@ -13,7 +13,7 @@ Consolidates functionality from:
|
|
|
13
13
|
import json
|
|
14
14
|
import shutil
|
|
15
15
|
import tempfile
|
|
16
|
-
from datetime import datetime
|
|
16
|
+
from datetime import datetime, timezone
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Dict, List, Optional
|
|
19
19
|
|
|
@@ -183,7 +183,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
183
183
|
"deployed_path": target_path,
|
|
184
184
|
"deployed_files": deployed_files,
|
|
185
185
|
"artifacts": [str(a) for a in artifacts],
|
|
186
|
-
"timestamp": datetime.now().isoformat(),
|
|
186
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
187
187
|
}
|
|
188
188
|
|
|
189
189
|
def verify(
|
|
@@ -300,7 +300,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
300
300
|
def _check_write_permission(self, path: Path) -> bool:
|
|
301
301
|
"""Check if we have write permission to path."""
|
|
302
302
|
try:
|
|
303
|
-
test_file = path / f".write_test_{datetime.now().timestamp()}"
|
|
303
|
+
test_file = path / f".write_test_{datetime.now(timezone.utc).timestamp()}"
|
|
304
304
|
test_file.touch()
|
|
305
305
|
test_file.unlink()
|
|
306
306
|
return True
|
|
@@ -310,7 +310,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
310
310
|
def _generate_deployment_id(self) -> str:
|
|
311
311
|
"""Generate unique deployment ID."""
|
|
312
312
|
return (
|
|
313
|
-
f"local_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
|
313
|
+
f"local_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
|
314
314
|
)
|
|
315
315
|
|
|
316
316
|
def _create_backup(self, context: DeploymentContext) -> Optional[Path]:
|
|
@@ -324,7 +324,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
324
324
|
backup_dir = Path(tempfile.gettempdir()) / "claude_mpm_backups"
|
|
325
325
|
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
326
326
|
|
|
327
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
327
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
328
328
|
backup_name = f"{target_path.name}.backup_{timestamp}"
|
|
329
329
|
backup_path = backup_dir / backup_name
|
|
330
330
|
|
|
@@ -343,7 +343,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
343
343
|
def _write_version_file(self, target_path: Path, version: str) -> None:
|
|
344
344
|
"""Write version file to deployment."""
|
|
345
345
|
version_file = target_path / ".version"
|
|
346
|
-
version_file.write_text(f"{version}\n{datetime.now().isoformat()}\n")
|
|
346
|
+
version_file.write_text(f"{version}\n{datetime.now(timezone.utc).isoformat()}\n")
|
|
347
347
|
|
|
348
348
|
# Agent deployment methods (consolidating agent_deployment.py patterns)
|
|
349
349
|
|
|
@@ -409,7 +409,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
409
409
|
|
|
410
410
|
for yaml_file in yaml_files:
|
|
411
411
|
try:
|
|
412
|
-
with open(
|
|
412
|
+
with yaml_file.open() as f:
|
|
413
413
|
data = yaml.safe_load(f)
|
|
414
414
|
# Basic agent structure validation
|
|
415
415
|
if not isinstance(data, dict):
|
|
@@ -425,11 +425,11 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
|
425
425
|
|
|
426
426
|
def _convert_json_to_yaml(self, json_path: Path) -> Path:
|
|
427
427
|
"""Convert JSON agent to YAML format."""
|
|
428
|
-
with open(
|
|
428
|
+
with json_path.open() as f:
|
|
429
429
|
data = json.load(f)
|
|
430
430
|
|
|
431
431
|
yaml_path = Path(tempfile.gettempdir()) / f"{json_path.stem}.yaml"
|
|
432
|
-
with open(
|
|
432
|
+
with yaml_path.open("w") as f:
|
|
433
433
|
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
|
|
434
434
|
|
|
435
435
|
return yaml_path
|
|
@@ -19,7 +19,7 @@ import json
|
|
|
19
19
|
import shutil
|
|
20
20
|
import subprocess
|
|
21
21
|
import tempfile
|
|
22
|
-
from datetime import datetime
|
|
22
|
+
from datetime import datetime, timezone
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
25
25
|
|
|
@@ -162,7 +162,7 @@ def prepare_deployment_artifact(
|
|
|
162
162
|
metadata = {
|
|
163
163
|
"source": str(source_path),
|
|
164
164
|
"type": artifact_type,
|
|
165
|
-
"created_at": datetime.now().isoformat(),
|
|
165
|
+
"created_at": datetime.now(timezone.utc).isoformat(),
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
# Auto-detect type
|
|
@@ -257,7 +257,7 @@ def verify_deployment_health(
|
|
|
257
257
|
"""
|
|
258
258
|
health = {
|
|
259
259
|
"status": "unknown",
|
|
260
|
-
"timestamp": datetime.now().isoformat(),
|
|
260
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
261
261
|
"checks": {},
|
|
262
262
|
"errors": [],
|
|
263
263
|
}
|
|
@@ -464,7 +464,7 @@ def get_version_info(path: Union[str, Path]) -> Dict[str, Any]:
|
|
|
464
464
|
|
|
465
465
|
if file_path.exists():
|
|
466
466
|
if version_file == "package.json":
|
|
467
|
-
with open(
|
|
467
|
+
with file_path.open() as f:
|
|
468
468
|
data = json.load(f)
|
|
469
469
|
version_info["version"] = data.get("version")
|
|
470
470
|
version_info["source"] = "package.json"
|
|
@@ -512,7 +512,7 @@ def update_version(
|
|
|
512
512
|
shutil.copy2(version_file, backup_file)
|
|
513
513
|
|
|
514
514
|
# Write new version
|
|
515
|
-
version_file.write_text(f"{new_version}\n{datetime.now().isoformat()}\n")
|
|
515
|
+
version_file.write_text(f"{new_version}\n{datetime.now(timezone.utc).isoformat()}\n")
|
|
516
516
|
return True
|
|
517
517
|
|
|
518
518
|
except Exception as e:
|
|
@@ -539,7 +539,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
|
|
|
539
539
|
hasher = hashlib.new(algorithm)
|
|
540
540
|
|
|
541
541
|
if path.is_file():
|
|
542
|
-
with open(
|
|
542
|
+
with path.open("rb") as f:
|
|
543
543
|
for chunk in iter(lambda: f.read(4096), b""):
|
|
544
544
|
hasher.update(chunk)
|
|
545
545
|
elif path.is_dir():
|
|
@@ -547,7 +547,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
|
|
|
547
547
|
for file_path in sorted(path.rglob("*")):
|
|
548
548
|
if file_path.is_file():
|
|
549
549
|
hasher.update(str(file_path.relative_to(path)).encode())
|
|
550
|
-
with open(
|
|
550
|
+
with file_path.open("rb") as f:
|
|
551
551
|
for chunk in iter(lambda: f.read(4096), b""):
|
|
552
552
|
hasher.update(chunk)
|
|
553
553
|
|
|
@@ -616,7 +616,7 @@ def load_env_file(env_file: Union[str, Path]) -> Dict[str, str]:
|
|
|
616
616
|
env_path = Path(env_file)
|
|
617
617
|
|
|
618
618
|
if env_path.exists():
|
|
619
|
-
with open(
|
|
619
|
+
with env_path.open() as f:
|
|
620
620
|
for line in f:
|
|
621
621
|
line = line.strip()
|
|
622
622
|
if line and not line.startswith("#") and "=" in line:
|
|
@@ -656,7 +656,7 @@ def export_env_to_file(env_vars: Dict[str, str], output_file: Union[str, Path])
|
|
|
656
656
|
output_path = Path(output_file)
|
|
657
657
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
658
658
|
|
|
659
|
-
with open(
|
|
659
|
+
with output_path.open("w") as f:
|
|
660
660
|
for key, value in env_vars.items():
|
|
661
661
|
# Escape special characters in value
|
|
662
662
|
if " " in value or '"' in value:
|
|
@@ -9,7 +9,7 @@ Consolidates Vercel deployment patterns from multiple services.
|
|
|
9
9
|
import json
|
|
10
10
|
import subprocess
|
|
11
11
|
import tempfile
|
|
12
|
-
from datetime import datetime
|
|
12
|
+
from datetime import datetime, timezone
|
|
13
13
|
from pathlib import Path
|
|
14
14
|
from typing import Any, Dict, List, Optional
|
|
15
15
|
|
|
@@ -203,13 +203,13 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
|
203
203
|
"deployed_path": deploy_dir,
|
|
204
204
|
"production": context.config.get("production", False),
|
|
205
205
|
"stdout": result.stdout,
|
|
206
|
-
"timestamp": datetime.now().isoformat(),
|
|
206
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
207
207
|
}
|
|
208
208
|
raise Exception("Could not parse deployment URL from Vercel output")
|
|
209
209
|
|
|
210
210
|
except subprocess.CalledProcessError as e:
|
|
211
211
|
self._logger.error(f"Vercel deployment failed: {e.stderr}")
|
|
212
|
-
raise Exception(f"Deployment failed: {e.stderr}")
|
|
212
|
+
raise Exception(f"Deployment failed: {e.stderr}") from e
|
|
213
213
|
|
|
214
214
|
def verify(
|
|
215
215
|
self, context: DeploymentContext, deployment_info: Dict[str, Any]
|
|
@@ -336,7 +336,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
|
336
336
|
health["checks"][f"function_{func_name}"] = (
|
|
337
337
|
response.status < 500
|
|
338
338
|
)
|
|
339
|
-
except:
|
|
339
|
+
except (urllib.error.URLError, OSError, TimeoutError):
|
|
340
340
|
health["checks"][f"function_{func_name}"] = False
|
|
341
341
|
|
|
342
342
|
# Determine overall status
|
|
@@ -416,7 +416,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
|
416
416
|
|
|
417
417
|
if vercel_config:
|
|
418
418
|
config_path = deploy_dir / "vercel.json"
|
|
419
|
-
with open(
|
|
419
|
+
with config_path.open("w") as f:
|
|
420
420
|
json.dump(vercel_config, f, indent=2)
|
|
421
421
|
return config_path
|
|
422
422
|
|
|
@@ -430,7 +430,7 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
|
430
430
|
|
|
431
431
|
if env_vars:
|
|
432
432
|
env_file = deploy_dir / ".env"
|
|
433
|
-
with open(
|
|
433
|
+
with env_file.open("w") as f:
|
|
434
434
|
for key, value in env_vars.items():
|
|
435
435
|
f.write(f"{key}={value}\n")
|
|
436
436
|
return env_file
|
|
@@ -472,5 +472,5 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
|
472
472
|
def _generate_deployment_id(self) -> str:
|
|
473
473
|
"""Generate unique deployment ID."""
|
|
474
474
|
return (
|
|
475
|
-
f"vercel_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
|
475
|
+
f"vercel_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
|
476
476
|
)
|
|
@@ -335,14 +335,14 @@ class UnifiedConfigManager(IConfigurationService, IUnifiedService):
|
|
|
335
335
|
|
|
336
336
|
# Save based on file extension
|
|
337
337
|
if target_path.suffix == ".json":
|
|
338
|
-
with open(
|
|
338
|
+
with target_path.open("w") as f:
|
|
339
339
|
json.dump(transformed_config, f, indent=2)
|
|
340
340
|
elif target_path.suffix in [".yaml", ".yml"]:
|
|
341
341
|
# Would use yaml library here
|
|
342
|
-
with open(
|
|
342
|
+
with target_path.open("w") as f:
|
|
343
343
|
f.write(str(transformed_config))
|
|
344
344
|
else:
|
|
345
|
-
with open(
|
|
345
|
+
with target_path.open("w") as f:
|
|
346
346
|
f.write(str(transformed_config))
|
|
347
347
|
|
|
348
348
|
return ConfigurationResult(
|
|
@@ -685,6 +685,6 @@ class UnifiedConfigManager(IConfigurationService, IUnifiedService):
|
|
|
685
685
|
|
|
686
686
|
def _get_timestamp(self) -> str:
|
|
687
687
|
"""Get current timestamp."""
|
|
688
|
-
from datetime import datetime
|
|
688
|
+
from datetime import datetime, timezone
|
|
689
689
|
|
|
690
|
-
return datetime.now().isoformat()
|
|
690
|
+
return datetime.now(timezone.utc).isoformat()
|
|
@@ -460,6 +460,6 @@ class UnifiedDeploymentService(IDeploymentService, IUnifiedService):
|
|
|
460
460
|
|
|
461
461
|
def _get_timestamp(self) -> str:
|
|
462
462
|
"""Get current timestamp."""
|
|
463
|
-
from datetime import datetime
|
|
463
|
+
from datetime import datetime, timezone
|
|
464
464
|
|
|
465
|
-
return datetime.now().isoformat()
|
|
465
|
+
return datetime.now(timezone.utc).isoformat()
|
|
@@ -321,7 +321,7 @@ class ConflictResolutionManager:
|
|
|
321
321
|
|
|
322
322
|
# Check content (simple heuristic)
|
|
323
323
|
try:
|
|
324
|
-
with open(
|
|
324
|
+
with file_path.open("rb") as f:
|
|
325
325
|
chunk = f.read(1024)
|
|
326
326
|
if b"\0" in chunk:
|
|
327
327
|
return True
|
|
@@ -596,7 +596,7 @@ class ConflictResolutionManager:
|
|
|
596
596
|
)
|
|
597
597
|
|
|
598
598
|
# Write resolved content
|
|
599
|
-
with open(
|
|
599
|
+
with file_path.open("w", encoding="utf-8") as f:
|
|
600
600
|
f.write(resolved_content)
|
|
601
601
|
|
|
602
602
|
return ConflictResolution(
|
|
@@ -147,10 +147,10 @@ class GitOperationsManager:
|
|
|
147
147
|
|
|
148
148
|
return result
|
|
149
149
|
|
|
150
|
-
except FileNotFoundError:
|
|
151
|
-
raise GitOperationError("Git is not installed or not in PATH")
|
|
150
|
+
except FileNotFoundError as e:
|
|
151
|
+
raise GitOperationError("Git is not installed or not in PATH") from e
|
|
152
152
|
except Exception as e:
|
|
153
|
-
raise GitOperationError(f"Error running Git command: {e}")
|
|
153
|
+
raise GitOperationError(f"Error running Git command: {e}") from e
|
|
154
154
|
|
|
155
155
|
def get_current_branch(self) -> str:
|
|
156
156
|
"""Get the current Git branch name."""
|