claude-mpm 4.5.8__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +20 -5
- claude_mpm/agents/agent_loader.py +19 -2
- claude_mpm/agents/base_agent_loader.py +5 -5
- claude_mpm/agents/frontmatter_validator.py +4 -4
- claude_mpm/agents/templates/agent-manager.json +3 -3
- claude_mpm/agents/templates/agentic-coder-optimizer.json +3 -3
- claude_mpm/agents/templates/api_qa.json +1 -1
- claude_mpm/agents/templates/clerk-ops.json +3 -3
- claude_mpm/agents/templates/code_analyzer.json +3 -3
- claude_mpm/agents/templates/dart_engineer.json +294 -0
- claude_mpm/agents/templates/data_engineer.json +3 -3
- claude_mpm/agents/templates/documentation.json +2 -2
- claude_mpm/agents/templates/engineer.json +2 -2
- claude_mpm/agents/templates/gcp_ops_agent.json +2 -2
- claude_mpm/agents/templates/imagemagick.json +1 -1
- claude_mpm/agents/templates/local_ops_agent.json +319 -41
- claude_mpm/agents/templates/memory_manager.json +2 -2
- claude_mpm/agents/templates/nextjs_engineer.json +2 -2
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/php-engineer.json +1 -1
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/prompt-engineer.json +6 -4
- claude_mpm/agents/templates/python_engineer.json +2 -2
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/react_engineer.json +3 -3
- claude_mpm/agents/templates/refactoring_engineer.json +3 -3
- claude_mpm/agents/templates/research.json +2 -2
- claude_mpm/agents/templates/security.json +2 -2
- claude_mpm/agents/templates/ticketing.json +2 -2
- claude_mpm/agents/templates/typescript_engineer.json +2 -2
- claude_mpm/agents/templates/vercel_ops_agent.json +2 -2
- claude_mpm/agents/templates/version_control.json +2 -2
- claude_mpm/agents/templates/web_qa.json +6 -6
- claude_mpm/agents/templates/web_ui.json +3 -3
- claude_mpm/cli/__init__.py +49 -19
- 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 +605 -21
- 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/configure_parser.py +5 -0
- 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/__init__.py +53 -17
- 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 +5 -5
- 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 +11 -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/response_tracking.py +16 -11
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +16 -13
- 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 +145 -161
- 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_config_loader.py +21 -0
- 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/loading/base_agent_manager.py +12 -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 +3 -3
- claude_mpm/services/claude_session_logger.py +4 -4
- 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 +169 -48
- claude_mpm/services/mcp_gateway/__init__.py +98 -94
- 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/event_emitter.py +1 -1
- 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 +788 -0
- 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 +597 -0
- claude_mpm/services/response_tracker.py +1 -1
- claude_mpm/services/session_management_service.py +1 -1
- claude_mpm/services/session_manager.py +6 -4
- 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.8.dist-info → claude_mpm-4.5.12.dist-info}/METADATA +1 -1
- {claude_mpm-4.5.8.dist-info → claude_mpm-4.5.12.dist-info}/RECORD +226 -223
- {claude_mpm-4.5.8.dist-info → claude_mpm-4.5.12.dist-info}/WHEEL +0 -0
- {claude_mpm-4.5.8.dist-info → claude_mpm-4.5.12.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.5.8.dist-info → claude_mpm-4.5.12.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.5.8.dist-info → claude_mpm-4.5.12.dist-info}/top_level.txt +0 -0
@@ -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."""
|
@@ -100,7 +100,7 @@ class SemanticVersion:
|
|
100
100
|
version += f"+{self.build}"
|
101
101
|
return version
|
102
102
|
|
103
|
-
def __lt__(self, other: "SemanticVersion") -> bool:
|
103
|
+
def __lt__(self, other: "SemanticVersion") -> bool:
|
104
104
|
"""Compare versions for sorting according to semver precedence.
|
105
105
|
|
106
106
|
Comparison Rules:
|
@@ -416,7 +416,7 @@ class SemanticVersionManager:
|
|
416
416
|
return self._parse_toml_version_regex(file_path)
|
417
417
|
|
418
418
|
try:
|
419
|
-
with open(
|
419
|
+
with file_path.open("rb") as f:
|
420
420
|
data = tomllib.load(f)
|
421
421
|
|
422
422
|
# Try different locations for version
|
@@ -437,7 +437,7 @@ class SemanticVersionManager:
|
|
437
437
|
def _parse_toml_version_regex(self, file_path: Path) -> Optional[str]:
|
438
438
|
"""Parse version from TOML file using regex."""
|
439
439
|
try:
|
440
|
-
with open(
|
440
|
+
with file_path.open() as f:
|
441
441
|
content = f.read()
|
442
442
|
|
443
443
|
# Look for version = "x.y.z" pattern
|
@@ -463,7 +463,7 @@ class SemanticVersionManager:
|
|
463
463
|
def _parse_version_file(self, file_path: Path) -> Optional[str]:
|
464
464
|
"""Parse version from simple version file."""
|
465
465
|
try:
|
466
|
-
with open(
|
466
|
+
with file_path.open() as f:
|
467
467
|
return f.read().strip()
|
468
468
|
except Exception:
|
469
469
|
return None
|
@@ -471,7 +471,7 @@ class SemanticVersionManager:
|
|
471
471
|
def _parse_pom_xml_version(self, file_path: Path) -> Optional[str]:
|
472
472
|
"""Parse version from Maven pom.xml."""
|
473
473
|
try:
|
474
|
-
with open(
|
474
|
+
with file_path.open() as f:
|
475
475
|
content = f.read()
|
476
476
|
|
477
477
|
# Simple regex to find version in pom.xml
|
@@ -673,7 +673,7 @@ class SemanticVersionManager:
|
|
673
673
|
def _update_toml_version(self, file_path: Path, new_version: str) -> bool:
|
674
674
|
"""Update version in TOML file."""
|
675
675
|
try:
|
676
|
-
with open(
|
676
|
+
with file_path.open() as f:
|
677
677
|
content = f.read()
|
678
678
|
|
679
679
|
# Replace version field
|
@@ -691,7 +691,7 @@ class SemanticVersionManager:
|
|
691
691
|
break
|
692
692
|
|
693
693
|
if updated:
|
694
|
-
with open(
|
694
|
+
with file_path.open("w") as f:
|
695
695
|
f.write(content)
|
696
696
|
return True
|
697
697
|
|
@@ -703,7 +703,7 @@ class SemanticVersionManager:
|
|
703
703
|
def _update_simple_version_file(self, file_path: Path, new_version: str) -> bool:
|
704
704
|
"""Update version in simple version file."""
|
705
705
|
try:
|
706
|
-
with open(
|
706
|
+
with file_path.open("w") as f:
|
707
707
|
f.write(new_version + "\n")
|
708
708
|
return True
|
709
709
|
except Exception:
|
@@ -712,7 +712,7 @@ class SemanticVersionManager:
|
|
712
712
|
def _update_pom_xml_version(self, file_path: Path, new_version: str) -> bool:
|
713
713
|
"""Update version in Maven pom.xml."""
|
714
714
|
try:
|
715
|
-
with open(
|
715
|
+
with file_path.open() as f:
|
716
716
|
content = f.read()
|
717
717
|
|
718
718
|
# Replace first version tag (project version)
|
@@ -722,7 +722,7 @@ class SemanticVersionManager:
|
|
722
722
|
new_content = re.sub(pattern, replacement, content, count=1)
|
723
723
|
|
724
724
|
if new_content != content:
|
725
|
-
with open(
|
725
|
+
with file_path.open("w") as f:
|
726
726
|
f.write(new_content)
|
727
727
|
return True
|
728
728
|
|
@@ -841,7 +841,7 @@ class SemanticVersionManager:
|
|
841
841
|
|
842
842
|
# Read existing changelog or create new one
|
843
843
|
if changelog_path.exists():
|
844
|
-
with open(
|
844
|
+
with changelog_path.open() as f:
|
845
845
|
existing_content = f.read()
|
846
846
|
|
847
847
|
# Insert new entry after title
|
@@ -864,7 +864,7 @@ class SemanticVersionManager:
|
|
864
864
|
content = f"# Changelog\n\n{new_entry}\n"
|
865
865
|
|
866
866
|
# Write updated changelog
|
867
|
-
with open(
|
867
|
+
with changelog_path.open("w") as f:
|
868
868
|
f.write(content)
|
869
869
|
|
870
870
|
self.logger.info(f"Updated {changelog_file} with version {version}")
|
@@ -945,7 +945,7 @@ class SemanticVersionManager:
|
|
945
945
|
versions = []
|
946
946
|
|
947
947
|
try:
|
948
|
-
with open(
|
948
|
+
with changelog_path.open() as f:
|
949
949
|
content = f.read()
|
950
950
|
|
951
951
|
# Find version entries
|
@@ -365,7 +365,7 @@ class EnhancedVersionParser:
|
|
365
365
|
package_file = self.project_root / "package.json"
|
366
366
|
if package_file.exists():
|
367
367
|
try:
|
368
|
-
with open(
|
368
|
+
with package_file.open() as f:
|
369
369
|
data = json.load(f)
|
370
370
|
version = data.get("version")
|
371
371
|
if version and self._version_pattern.match(version):
|
@@ -24,6 +24,10 @@ import time
|
|
24
24
|
from contextlib import contextmanager, suppress
|
25
25
|
from typing import Any, Dict, Optional, Tuple, Union
|
26
26
|
|
27
|
+
from claude_mpm.core.logging_utils import get_logger
|
28
|
+
|
29
|
+
logger = get_logger(__name__)
|
30
|
+
|
27
31
|
|
28
32
|
class StateStorage:
|
29
33
|
"""Reliable state storage with atomic operations."""
|
@@ -37,11 +41,6 @@ class StateStorage:
|
|
37
41
|
self.storage_dir = storage_dir or Path.home() / ".claude-mpm" / "storage"
|
38
42
|
self.storage_dir.mkdir(parents=True, exist_ok=True)
|
39
43
|
|
40
|
-
# Logging
|
41
|
-
from claude_mpm.core.logging_utils import get_logger
|
42
|
-
|
43
|
-
logger = get_logger(__name__)
|
44
|
-
|
45
44
|
# File locking support (Unix-like systems)
|
46
45
|
self.supports_locking = platform.system() != "Windows"
|
47
46
|
|
@@ -80,7 +79,7 @@ logger = get_logger(__name__)
|
|
80
79
|
with gzip.open(file_path, "wt", encoding="utf-8") as f:
|
81
80
|
json.dump(data, f, indent=2, default=str)
|
82
81
|
else:
|
83
|
-
with open(
|
82
|
+
with file_path.open("w") as f:
|
84
83
|
json.dump(data, f, indent=2, default=str)
|
85
84
|
|
86
85
|
self.write_count += 1
|
@@ -119,7 +118,7 @@ logger = get_logger(__name__)
|
|
119
118
|
with gzip.open(file_path, "rt", encoding="utf-8") as f:
|
120
119
|
data = json.load(f)
|
121
120
|
else:
|
122
|
-
with open(
|
121
|
+
with file_path.open() as f:
|
123
122
|
data = json.load(f)
|
124
123
|
|
125
124
|
self.read_count += 1
|
@@ -160,7 +159,7 @@ logger = get_logger(__name__)
|
|
160
159
|
with gzip.open(file_path, "wb") as f:
|
161
160
|
pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
|
162
161
|
else:
|
163
|
-
with open(
|
162
|
+
with file_path.open("wb") as f:
|
164
163
|
pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)
|
165
164
|
|
166
165
|
self.write_count += 1
|
@@ -199,7 +198,7 @@ logger = get_logger(__name__)
|
|
199
198
|
with gzip.open(file_path, "rb") as f:
|
200
199
|
data = pickle.load(f)
|
201
200
|
else:
|
202
|
-
with open(
|
201
|
+
with file_path.open("rb") as f:
|
203
202
|
data = pickle.load(f)
|
204
203
|
|
205
204
|
self.read_count += 1
|
@@ -328,7 +327,7 @@ logger = get_logger(__name__)
|
|
328
327
|
|
329
328
|
# Calculate checksum
|
330
329
|
hasher = hashlib.sha256()
|
331
|
-
with open(
|
330
|
+
with file_path.open("rb") as f:
|
332
331
|
for chunk in iter(lambda: f.read(4096), b""):
|
333
332
|
hasher.update(chunk)
|
334
333
|
|
@@ -336,7 +335,7 @@ logger = get_logger(__name__)
|
|
336
335
|
|
337
336
|
# Write checksum file
|
338
337
|
checksum_path = file_path.with_suffix(file_path.suffix + ".sha256")
|
339
|
-
with open(
|
338
|
+
with checksum_path.open("w") as f:
|
340
339
|
f.write(checksum)
|
341
340
|
|
342
341
|
except Exception as e:
|
@@ -359,12 +358,12 @@ logger = get_logger(__name__)
|
|
359
358
|
return True # No checksum to verify
|
360
359
|
|
361
360
|
# Read expected checksum
|
362
|
-
with open(
|
361
|
+
with checksum_path.open() as f:
|
363
362
|
expected = f.read().strip()
|
364
363
|
|
365
364
|
# Calculate actual checksum
|
366
365
|
hasher = hashlib.sha256()
|
367
|
-
with open(
|
366
|
+
with file_path.open("rb") as f:
|
368
367
|
for chunk in iter(lambda: f.read(4096), b""):
|
369
368
|
hasher.update(chunk)
|
370
369
|
|