Files
hermes-recovery/scripts/hermes-consolidate.sh
T

80 lines
2.8 KiB
Bash
Executable File

#!/bin/bash
# hermes-consolidate.sh — Auto-consolidate Hermes memory every 10 min.
#
# ORDER OF OPERATIONS (backup BEFORE prune is a hard guarantee):
# 1. Dump current MEMORY.md entries to JSON.
# 2. Upload that JSON to S3 (s3://hermes-vps-backups/live/memories/memory-backup.json).
# -> If the S3 upload fails, we ABORT before pruning. Nothing is deleted
# unless we have a fresh off-box backup.
# 3. Run the pruner (pattern prune + size safety valve + 7-day fact-store prune).
# 4. Keep a local timestamped pre-prune copy for fast restore.
#
# Target: keep MEMORY.md under ~70% of the 10,000-char limit (7,000 chars).
# Silent on success, loud on failure (no_agent friendly).
set -euo pipefail
HERMES_HOME="${HERMES_HOME:-$HOME/.hermes}"
MEMORY_MD="$HERMES_HOME/memories/MEMORY.md"
CONSOLIDATE_PY="$HERMES_HOME/scripts/hermes-consolidate.py"
BACKUP_DIR="$HERMES_HOME/memories/.consolidate-backups"
ENDPOINT="https://s3.us-east-1.wasabisys.com"
S3_BUCKET="hermes-vps-backups"
S3_KEY="live/memories/memory-backup.json"
LOG="/var/log/hermes-consolidate.log"
log() { echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $*" >> "$LOG"; }
# Source AWS CLI venv
if [ -f /opt/awscli-venv/bin/activate ]; then
# shellcheck disable=SC1091
source /opt/awscli-venv/bin/activate
fi
mkdir -p "$BACKUP_DIR"
if [ ! -f "$MEMORY_MD" ]; then
log "FAILED: MEMORY.md not found at $MEMORY_MD"
echo "RESULT:FAIL|MEMORY.md not found"
exit 1
fi
TS=$(date -u +%Y%m%d_%H%M%S)
LOCAL_BACKUP="$BACKUP_DIR/memory-backup-${TS}.json"
# --- Step 1: dump current entries to JSON (no mutation) ---
if ! python3 "$CONSOLIDATE_PY" --dump-only > "$LOCAL_BACKUP" 2>>"$LOG"; then
log "FAILED: dump step failed"
echo "RESULT:FAIL|dump failed"
rm -f "$LOCAL_BACKUP"
exit 1
fi
# --- Step 2: upload backup to S3 BEFORE pruning ---
if ! aws s3 cp "$LOCAL_BACKUP" "s3://$S3_BUCKET/$S3_KEY" \
--endpoint-url "$ENDPOINT" --quiet 2>>"$LOG"; then
log "FAILED: S3 backup upload failed — ABORTING before prune (nothing deleted)"
echo "RESULT:FAIL|S3 backup failed, prune aborted"
exit 1
fi
# Also keep a timestamped copy in S3 for point-in-time restore.
aws s3 cp "$LOCAL_BACKUP" \
"s3://$S3_BUCKET/live/memories/history/memory-backup-${TS}.json" \
--endpoint-url "$ENDPOINT" --quiet 2>>"$LOG" || true
log "Backup uploaded to s3://$S3_BUCKET/$S3_KEY ($(stat --printf='%s' "$LOCAL_BACKUP") bytes)"
# --- Step 3: prune (safe now that backup is off-box) ---
PRUNE_OUT=$(python3 "$CONSOLIDATE_PY" --prune-facts 2>&1 >/dev/null) || {
log "FAILED: prune step failed: $PRUNE_OUT"
echo "RESULT:FAIL|prune failed"
exit 1
}
log "$PRUNE_OUT"
# --- Step 4: local retention — keep last 48h of pre-prune copies ---
find "$BACKUP_DIR" -name "memory-backup-*.json" -mmin +2880 -delete 2>/dev/null || true
# Echo the pruner RESULT line for cron visibility
echo "$PRUNE_OUT"
exit 0