Files
openclaw/scripts/memory-restore-from-db.sh

119 lines
3.1 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
set -euo pipefail
WORKSPACE="${WORKSPACE:-/home/openclaw/.openclaw/workspace}"
ENV_FILE="${MEMORY_RESTORE_ENV_FILE:-$WORKSPACE/.env}"
log(){
echo "[$(date -u +'%F %T UTC')] $*"
}
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
else
log "warn: env file not found: $ENV_FILE"
fi
if ! command -v psql >/dev/null 2>&1; then
log "error: psql is not installed; cannot restore memory from Postgres"
exit 3
fi
CONN_ARGS=()
if [[ -n "${MEMORY_DB_URL:-}" ]]; then
CONN_ARGS+=("$MEMORY_DB_URL")
else
missing=()
for v in MEMORY_DB_HOST MEMORY_DB_PORT MEMORY_DB_NAME MEMORY_DB_USER MEMORY_DB_PASSWORD; do
[[ -n "${!v:-}" ]] || missing+=("$v")
done
if (( ${#missing[@]} > 0 )); then
log "warn: missing DB env vars: ${missing[*]}"
log "warn: restore skipped (graceful fallback)"
exit 2
fi
export PGHOST="$MEMORY_DB_HOST"
export PGPORT="$MEMORY_DB_PORT"
export PGDATABASE="$MEMORY_DB_NAME"
export PGUSER="$MEMORY_DB_USER"
export PGPASSWORD="$MEMORY_DB_PASSWORD"
export PGSSLMODE="${MEMORY_DB_SSLMODE:-prefer}"
fi
mkdir -p "$WORKSPACE/memory/backups"
TS="$(date -u +'%Y%m%dT%H%M%SZ')"
BACKUP_DIR="$WORKSPACE/memory/backups/restore-$TS"
mkdir -p "$BACKUP_DIR"
# Backup current files before restore.
if [[ -f "$WORKSPACE/MEMORY.md" ]]; then
cp "$WORKSPACE/MEMORY.md" "$BACKUP_DIR/MEMORY.md"
fi
if [[ -d "$WORKSPACE/memory" ]]; then
find "$WORKSPACE/memory" -maxdepth 1 -type f -name '*.md' -print0 | while IFS= read -r -d '' f; do
cp "$f" "$BACKUP_DIR/$(basename "$f")"
done
fi
TMP_OUT="$(mktemp)"
trap 'rm -f "$TMP_OUT"' EXIT
SQL="SELECT source_path, encode(convert_to(content, 'UTF8'), 'base64') AS content_b64 FROM mem_items WHERE source_path = 'MEMORY.md' OR source_path ~ '^memory/[^/]+\\.md$' ORDER BY source_path;"
if ! psql "${CONN_ARGS[@]}" -X -A -t -F $'\t' -c "$SQL" > "$TMP_OUT"; then
log "error: Postgres query failed"
exit 4
fi
if [[ ! -s "$TMP_OUT" ]]; then
log "warn: no rows returned from mem_items for memory files"
exit 5
fi
python3 - <<'PY' "$WORKSPACE" "$TMP_OUT"
import base64
import pathlib
import sys
workspace = pathlib.Path(sys.argv[1]).resolve()
rows_file = pathlib.Path(sys.argv[2])
restored = 0
for raw in rows_file.read_text(encoding='utf-8', errors='replace').splitlines():
if not raw.strip():
continue
try:
source_path, b64 = raw.split('\t', 1)
except ValueError:
continue
source_path = source_path.strip()
allowed = source_path == 'MEMORY.md' or (
source_path.startswith('memory/') and source_path.endswith('.md') and '/' not in source_path[len('memory/'):]
)
if not allowed:
continue
target = (workspace / source_path).resolve()
if workspace not in target.parents and target != workspace / 'MEMORY.md':
continue
target.parent.mkdir(parents=True, exist_ok=True)
content = base64.b64decode(b64.encode('ascii'))
target.write_bytes(content)
restored += 1
print(f"restored_files={restored}")
if restored == 0:
raise SystemExit(6)
PY
log "ok: memory restore completed (backup: $BACKUP_DIR)"