backup-2025-12-19-20: Automated backup - 10 files changed

📋 Files modified: 10
 Timestamp: 2025-12-19 20:27:31 UTC
🔒 Security: PASSED (no secrets detected)
💾 Automated by Git Agent
This commit is contained in:
2025-12-19 21:27:31 +01:00
parent 5ca16ec33f
commit 050eeeaff2
15 changed files with 2856 additions and 25 deletions

235
tools/slash_commands.py Normal file
View File

@ -0,0 +1,235 @@
#!/usr/bin/env python3
"""
OpenCode Slash Commands for Git Agent
Provides custom slash commands for Git operations in the Uniswap Auto CLP project
"""
import os
import sys
import subprocess
import json
from datetime import datetime
from typing import Dict, Any, List, Optional
class GitSlashCommand:
"""Base class for Git-related slash commands"""
def __init__(self):
self.project_root = "K:\\Projects\\uniswap_auto_clp"
self.git_agent_path = os.path.join(self.project_root, "tools", "git_agent.py")
def run_git_agent(self, args: List[str]) -> Dict[str, Any]:
"""Execute git_agent.py with specified arguments"""
try:
cmd = ["python", self.git_agent_path] + args
result = subprocess.run(
cmd,
cwd=self.project_root,
capture_output=True,
text=True,
check=False
)
return {
"success": result.returncode == 0,
"stdout": result.stdout.strip(),
"stderr": result.stderr.strip(),
"returncode": result.returncode
}
except Exception as e:
return {
"success": False,
"stdout": "",
"stderr": str(e),
"returncode": -1
}
def get_backup_branches(self) -> List[str]:
"""Get list of backup branches for restore functionality"""
try:
result = subprocess.run(
["git", "branch", "-a"],
cwd=self.project_root,
capture_output=True,
text=True,
check=False
)
if result.returncode == 0:
branches = []
for line in result.stdout.strip().split('\n'):
branch = line.strip().replace('* ', '').replace('remotes/origin/', '')
if branch.startswith('backup-'):
branches.append(branch)
branches.sort(key=lambda x: x.replace('backup-', ''), reverse=True)
return branches
return []
except Exception:
return []
def format_backup_time(self, time_input: str) -> Optional[str]:
"""Convert user time input to backup branch name format"""
try:
# Handle different input formats
if len(time_input) == 10: # YYYY-MM-DD
return f"backup-{time_input}"
elif len(time_input) == 13: # YYYY-MM-DD-HH
return f"backup-{time_input}"
elif len(time_input) == 8: # MM-DD-HH
current_year = datetime.now().year
return f"backup-{current_year}-{time_input}"
else:
# Try to match partial patterns
if '-' in time_input:
parts = time_input.split('-')
if len(parts) == 2 and len(parts[1]) == 2: # MM-DD
current_year = datetime.now().year
return f"backup-{current_year}-{parts[0]}-{parts[1]}-00"
return None
except Exception:
return None
class GitBackupCommand(GitSlashCommand):
"""Handle /git-backup command"""
def execute(self) -> str:
result = self.run_git_agent(["--backup"])
if result["success"]:
return "✅ **Backup completed successfully**\n\nAutomated backup created and pushed to remote repository."
else:
error_msg = result["stderr"] or result["stdout"] or "Unknown error"
return f"❌ **Backup failed**\n\nError: {error_msg}"
class GitStatusCommand(GitSlashCommand):
"""Handle /git-status command"""
def execute(self) -> str:
result = self.run_git_agent(["--status"])
if result["success"]:
return f"📊 **Git Agent Status**\n\n```\n{result['stdout']}\n```"
else:
error_msg = result["stderr"] or result["stdout"] or "Unknown error"
return f"❌ **Status check failed**\n\nError: {error_msg}"
class GitCleanupCommand(GitSlashCommand):
"""Handle /git-cleanup command"""
def execute(self) -> str:
result = self.run_git_agent(["--cleanup"])
if result["success"]:
return "✅ **Cleanup completed**\n\nOld backup branches have been removed according to retention policy."
else:
error_msg = result["stderr"] or result["stdout"] or "Unknown error"
return f"❌ **Cleanup failed**\n\nError: {error_msg}"
class GitRestoreCommand(GitSlashCommand):
"""Handle /git-restore command"""
def execute(self, time_input: str = None) -> str:
if not time_input:
# Show available backups
branches = self.get_backup_branches()
if not branches:
return "📂 **No backup branches found**\n\nUse `/git-backup` to create a backup first."
response = "📂 **Available Backups**\n\nChoose a backup to restore:\n"
for i, branch in enumerate(branches[:10]): # Show last 10
# Extract timestamp from branch name
timestamp = branch.replace('backup-', '')
formatted_time = self.format_timestamp_display(timestamp)
response += f"• `{timestamp}` - {formatted_time}\n"
if len(branches) > 10:
response += f"\n... and {len(branches) - 10} more backups"
response += "\n\n**Usage:** `/git-restore <timestamp>` (e.g., `2025-12-19-14`)"
return response
# Try to restore specific backup
branch_name = self.format_backup_time(time_input)
if not branch_name:
return f"❌ **Invalid time format**\n\nExpected format: `YYYY-MM-DD-HH` (e.g., `2025-12-19-14`)"
# Check if branch exists
branches = self.get_backup_branches()
matching_branches = [b for b in branches if branch_name in b]
if not matching_branches:
return f"❌ **Backup not found**\n\nNo backup found for: `{time_input}`\n\nUse `/git-restore` to see available backups."
# Use the most recent matching branch
target_branch = matching_branches[0]
try:
# Checkout the backup branch
result = subprocess.run(
["git", "checkout", target_branch],
cwd=self.project_root,
capture_output=True,
text=True,
check=False
)
if result.returncode == 0:
timestamp = target_branch.replace('backup-', '')
formatted_time = self.format_timestamp_display(timestamp)
return f"✅ **Restored to backup**\n\nBranch: `{target_branch}`\nTime: {formatted_time}\n\n⚠️ **Note:** You're now on a backup branch. Use `git checkout main` to return to the main branch when done."
else:
return f"❌ **Restore failed**\n\nError: {result.stderr.strip()}"
except Exception as e:
return f"❌ **Restore failed**\n\nError: {str(e)}"
def format_timestamp_display(self, timestamp: str) -> str:
"""Format backup timestamp for display"""
try:
if len(timestamp) >= 10:
date_part = timestamp[:10]
if len(timestamp) >= 13:
time_part = timestamp[11:13] + ":00"
return f"{date_part} {time_part} UTC"
return f"{date_part}"
return timestamp
except Exception:
return timestamp
# Command registry
COMMAND_HANDLERS = {
"git-backup": GitBackupCommand,
"git-status": GitStatusCommand,
"git-cleanup": GitCleanupCommand,
"git-restore": GitRestoreCommand,
}
def execute_command(command_name: str, args: List[str] = None) -> str:
"""Execute a slash command and return the response"""
if args is None:
args = []
handler_class = COMMAND_HANDLERS.get(command_name)
if not handler_class:
return f"❌ **Unknown command:** `{command_name}`"
handler = handler_class()
if command_name == "git-restore":
return handler.execute(args[0] if args else None)
else:
return handler.execute()
if __name__ == "__main__":
# Test functionality
if len(sys.argv) > 1:
command = sys.argv[1]
command_args = sys.argv[2:] if len(sys.argv) > 2 else []
print(execute_command(command, command_args))
else:
print("Available commands:")
for cmd in COMMAND_HANDLERS.keys():
print(f" /{cmd}")