claude-mpm 4.5.11__py3-none-any.whl → 4.5.13__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/BASE_ENGINEER.md +47 -0
- claude_mpm/agents/BASE_QA.md +60 -0
- claude_mpm/agents/frontmatter_validator.py +4 -4
- claude_mpm/agents/templates/nextjs_engineer.json +2 -2
- claude_mpm/agents/templates/qa.json +13 -3
- claude_mpm/agents/templates/react_engineer.json +2 -2
- claude_mpm/agents/templates/typescript_engineer.json +2 -2
- claude_mpm/agents/templates/web_qa.json +14 -3
- 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 +6 -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 +6 -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 +9 -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 +5 -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 +11 -16
- claude_mpm/services/port_manager.py +2 -2
- claude_mpm/services/project/analyzer.py +3 -3
- claude_mpm/services/project/archive_manager.py +17 -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 +19 -8
- claude_mpm/services/project/registry.py +4 -4
- claude_mpm/services/project_port_allocator.py +7 -12
- 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 +8 -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 +11 -11
- claude_mpm/services/unified/deployment_strategies/utils.py +11 -9
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -9
- 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.13.dist-info}/METADATA +1 -1
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/RECORD +190 -190
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/WHEEL +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.5.11.dist-info → claude_mpm-4.5.13.dist-info}/top_level.txt +0 -0
@@ -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
|
@@ -309,9 +309,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
309
309
|
|
310
310
|
def _generate_deployment_id(self) -> str:
|
311
311
|
"""Generate unique deployment ID."""
|
312
|
-
return (
|
313
|
-
f"local_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
314
|
-
)
|
312
|
+
return f"local_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
315
313
|
|
316
314
|
def _create_backup(self, context: DeploymentContext) -> Optional[Path]:
|
317
315
|
"""Create backup of target before deployment."""
|
@@ -324,7 +322,7 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
324
322
|
backup_dir = Path(tempfile.gettempdir()) / "claude_mpm_backups"
|
325
323
|
backup_dir.mkdir(parents=True, exist_ok=True)
|
326
324
|
|
327
|
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
325
|
+
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
328
326
|
backup_name = f"{target_path.name}.backup_{timestamp}"
|
329
327
|
backup_path = backup_dir / backup_name
|
330
328
|
|
@@ -343,7 +341,9 @@ class LocalDeploymentStrategy(DeploymentStrategy):
|
|
343
341
|
def _write_version_file(self, target_path: Path, version: str) -> None:
|
344
342
|
"""Write version file to deployment."""
|
345
343
|
version_file = target_path / ".version"
|
346
|
-
version_file.write_text(
|
344
|
+
version_file.write_text(
|
345
|
+
f"{version}\n{datetime.now(timezone.utc).isoformat()}\n"
|
346
|
+
)
|
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,9 @@ def update_version(
|
|
512
512
|
shutil.copy2(version_file, backup_file)
|
513
513
|
|
514
514
|
# Write new version
|
515
|
-
version_file.write_text(
|
515
|
+
version_file.write_text(
|
516
|
+
f"{new_version}\n{datetime.now(timezone.utc).isoformat()}\n"
|
517
|
+
)
|
516
518
|
return True
|
517
519
|
|
518
520
|
except Exception as e:
|
@@ -539,7 +541,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
|
|
539
541
|
hasher = hashlib.new(algorithm)
|
540
542
|
|
541
543
|
if path.is_file():
|
542
|
-
with open(
|
544
|
+
with path.open("rb") as f:
|
543
545
|
for chunk in iter(lambda: f.read(4096), b""):
|
544
546
|
hasher.update(chunk)
|
545
547
|
elif path.is_dir():
|
@@ -547,7 +549,7 @@ def calculate_checksum(path: Union[str, Path], algorithm: str = "sha256") -> str
|
|
547
549
|
for file_path in sorted(path.rglob("*")):
|
548
550
|
if file_path.is_file():
|
549
551
|
hasher.update(str(file_path.relative_to(path)).encode())
|
550
|
-
with open(
|
552
|
+
with file_path.open("rb") as f:
|
551
553
|
for chunk in iter(lambda: f.read(4096), b""):
|
552
554
|
hasher.update(chunk)
|
553
555
|
|
@@ -616,7 +618,7 @@ def load_env_file(env_file: Union[str, Path]) -> Dict[str, str]:
|
|
616
618
|
env_path = Path(env_file)
|
617
619
|
|
618
620
|
if env_path.exists():
|
619
|
-
with open(
|
621
|
+
with env_path.open() as f:
|
620
622
|
for line in f:
|
621
623
|
line = line.strip()
|
622
624
|
if line and not line.startswith("#") and "=" in line:
|
@@ -656,7 +658,7 @@ def export_env_to_file(env_vars: Dict[str, str], output_file: Union[str, Path])
|
|
656
658
|
output_path = Path(output_file)
|
657
659
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
658
660
|
|
659
|
-
with open(
|
661
|
+
with output_path.open("w") as f:
|
660
662
|
for key, value in env_vars.items():
|
661
663
|
# Escape special characters in value
|
662
664
|
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
|
@@ -471,6 +471,4 @@ class VercelDeploymentStrategy(DeploymentStrategy):
|
|
471
471
|
|
472
472
|
def _generate_deployment_id(self) -> str:
|
473
473
|
"""Generate unique deployment ID."""
|
474
|
-
return (
|
475
|
-
f"vercel_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
476
|
-
)
|
474
|
+
return f"vercel_{datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')}_{id(self) % 10000:04d}"
|
@@ -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):
|