#!/bin/bash # Hermes Sync Script - 双向同步记忆和技能 # 使用方法: # ./sync.sh pull - 从远程拉取到本地 # ./sync.sh push - 从本地上传到远程 # ./sync.sh sync - 双向同步 set -e HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}" SYNC_DIR="/root/hermes-sync-tmp" cd "$SYNC_DIR" RED='\033[0;31m' GREEN='\033[0;32m' NC='\033[0m' info() { echo -e "${GREEN}[$(date '+%H:%M:%S')]${NC} $*"; } error() { echo -e "${RED}[$(date '+%H:%M:%S')] ERROR:${NC} $*"; } pull() { info "Pulling from remote..." # Fetch remote changes git fetch origin main 2>/dev/null || { info "Remote empty, skipping pull"; return 0; } # Pull with rebase (preserves local changes) if git diff HEAD origin/main --quiet 2>/dev/null; then info "Already up to date" return 0 fi # Stash local changes first if ! git diff --quiet; then info "Stashing local changes..." git stash push -m "local $(date)" || true fi # Pull remote if git rev-parse origin/main >/dev/null 2>&1; then git rebase origin/main || { error "Rebase conflict! Resolve manually in $SYNC_DIR" git rebase --abort git stash pop return 1 } fi # Restore stashed changes if git stash list | grep -q "local"; then info "Restoring local changes..." git stash pop || true fi # Copy synced content to hermes home cp "$SYNC_DIR/memories/MEMORY.md" "$HERMES_HOME/memories/MEMORY.md" 2>/dev/null || true # Sync skills (merge mode - don't delete local) if [ -d "$SYNC_DIR/skills" ] && [ "$(ls -A "$SYNC_DIR/skills" 2>/dev/null)" ]; then rsync -a --ignore-existing "$SYNC_DIR/skills/" "$HERMES_HOME/skills/" 2>/dev/null || \ cp -rn "$SYNC_DIR/skills/"* "$HERMES_HOME/skills/" 2>/dev/null || true fi info "Pull complete" } push() { info "Pushing to remote..." # Copy current hermes content to sync dir cp "$HERMES_HOME/memories/MEMORY.md" "$SYNC_DIR/memories/MEMORY.md" 2>/dev/null || true # Sync skills (only add new ones, don't overwrite existing local modifications) if [ -d "$HERMES_HOME/skills" ]; then rsync -a --update "$HERMES_HOME/skills/" "$SYNC_DIR/skills/" 2>/dev/null || \ cp -rn "$HERMES_HOME/skills/"* "$SYNC_DIR/skills/" 2>/dev/null || true fi # Commit if there are changes if git diff --quiet && git diff --cached --quiet; then info "Nothing to push" return 0 fi git add -A git commit -m "Sync $(date '+%Y-%m-%d %H:%M')" || true git push origin main || { error "Push failed!"; return 1; } info "Push complete" } case "${1:-}" in pull) pull ;; push) push ;; sync) pull; push ;; *) echo "Usage: $0 {pull|push|sync}"; exit 1 ;; esac