#!/usr/bin/env bash set -euo pipefail MEMORY_DIR="${OPENCODE_MEMORY_DIR:-/root/.local/share/opencode/opencode-memory}" HOOK="$MEMORY_DIR/.git/hooks/post-commit" BRANCH="master" WRAPPER_PATH="${MEMORY_WRAPPER_PATH:-/usr/local/lib/node_modules/@mathew-cf/opencode-memory/node_modules/@mathew-cf/rag-cli/bin/rag.js}" # Pick a Python that can import src.memory: prefer workspace .venv, then CWD # .venv, then system python3. Override via MEMORY_WRAPPER_PYTHON for tests. if [ -n "${OPENCODE_WORKSPACE:-}" ] && [ -x "${OPENCODE_WORKSPACE}/.venv/bin/python" ]; then MEMORY_PYTHON="${MEMORY_WRAPPER_PYTHON:-${OPENCODE_WORKSPACE}/.venv/bin/python}" elif [ -x ".venv/bin/python" ]; then MEMORY_PYTHON="${MEMORY_WRAPPER_PYTHON:-.venv/bin/python}" else MEMORY_PYTHON="${MEMORY_WRAPPER_PYTHON:-python3}" fi EXPECTED_HOOK="#!/bin/bash git push origin ${BRANCH} 2>/dev/null || true" if [ -z "${OPENCODE_MEMORY_REMOTE:-}" ]; then echo "ERROR: OPENCODE_MEMORY_REMOTE not set" >&2 exit 1 fi REMOTE="${OPENCODE_MEMORY_REMOTE}" echo "memory setup: $MEMORY_DIR" # 1. MEMORY_DIR exists? → mkdir -p if [ ! -d "$MEMORY_DIR" ]; then mkdir -p "$MEMORY_DIR" echo " [1/6] created directory: $MEMORY_DIR" else echo " [1/6] directory exists" fi # 2. .git exists? → clone (no) | pull --ff-only (yes) if [ ! -d "$MEMORY_DIR/.git" ]; then echo " [2/6] cloning remote: $REMOTE" # Ensure GITHUB_TOKEN is used for HTTPS git operations (non-interactive). # Idempotent: git config --global overwrites (not duplicates) the value. if [ -n "${GITHUB_TOKEN:-}" ]; then git config --global url."https://x-access-token:${GITHUB_TOKEN}@github.com/".insteadOf https://github.com/ fi git clone --origin origin "$REMOTE" "$MEMORY_DIR" || { echo "ERROR: clone failed" >&2; exit 1; } git -C "$MEMORY_DIR" checkout "$BRANCH" 2>/dev/null || true else echo " [2/6] pulling latest (ff-only)" git -C "$MEMORY_DIR" pull --ff-only origin "$BRANCH" 2>/dev/null || \ echo " pull skipped (no upstream or offline)" fi # 3. remote origin correct? → set-url (no) | noop (yes) CURRENT_REMOTE="$(git -C "$MEMORY_DIR" remote get-url origin 2>/dev/null || echo "")" if [ "$CURRENT_REMOTE" != "$REMOTE" ]; then echo " [3/6] fixing remote: $CURRENT_REMOTE → $REMOTE" git -C "$MEMORY_DIR" remote set-url origin "$REMOTE" else echo " [3/6] remote correct" fi # 4. post-commit hook exists + content correct? → create/fix (no) | noop (yes) NEEDS_HOOK=0 if [ ! -f "$HOOK" ]; then NEEDS_HOOK=1 elif [ "$(cat "$HOOK")" != "$EXPECTED_HOOK" ]; then NEEDS_HOOK=1 fi if [ "$NEEDS_HOOK" -eq 1 ]; then echo " [4/6] installing post-commit hook (auto-push)" mkdir -p "$(dirname "$HOOK")" printf '%s\n' "$EXPECTED_HOOK" > "$HOOK" chmod +x "$HOOK" else echo " [4/6] hook correct" fi # 5. .rag index exists? → memory index (no) | noop (yes) if "$MEMORY_PYTHON" -c "import src.memory" >/dev/null 2>&1; then if [ ! -d "$MEMORY_DIR/.rag" ]; then echo " [5/7] building RAG index (memory CLI)" ( "$MEMORY_PYTHON" -m src.memory index "$MEMORY_DIR" -o "$MEMORY_DIR/.rag" ) 2>&1 \ || echo " memory index failed — continuing" else echo " [5/7] RAG index exists" fi else echo " [5/7] memory CLI not available — skipping index" fi # 5b. JS wrapper for opencode-memory plugin — delegates rag CLI calls to # Python memory CLI. Idempotent (content check via cmp), backs up # original once. WRAPPER_DIR="$(dirname "$WRAPPER_PATH")" mkdir -p "$WRAPPER_DIR" WRAPPER_CONTENT='#!/usr/bin/env node // Generated by setup-memory.sh — delegates rag CLI calls to Python memory CLI const { spawnSync } = require("child_process"); const py = process.env.MEMORY_WRAPPER_PYTHON || "'"$MEMORY_PYTHON"'"; const r = spawnSync(py, ["-m", "src.memory", ...process.argv.slice(2)], { stdio: "inherit", cwd: process.env.OPENCODE_WORKSPACE || process.cwd() }); process.exit(r.status || 0); ' if [ -f "$WRAPPER_PATH" ] && cmp -s "$WRAPPER_PATH" /dev/stdin <<<"$WRAPPER_CONTENT"; then echo " [5b/7] wrapper correct" else if [ -f "$WRAPPER_PATH" ]; then if [ ! -f "${WRAPPER_PATH}.orig" ]; then cp "$WRAPPER_PATH" "${WRAPPER_PATH}.orig" echo " [5b/7] backed up original wrapper → ${WRAPPER_PATH}.orig" fi fi printf '%s\n' "$WRAPPER_CONTENT" > "$WRAPPER_PATH" chmod +x "$WRAPPER_PATH" echo " [5b/7] generated wrapper (delegates → python memory CLI)" fi # 6. status echo " [7/7] done" echo "" echo "memory: ready at $MEMORY_DIR" echo " remote: $REMOTE" echo " branch: $BRANCH" echo " auto-push: enabled (post-commit hook)"