opencode-config/.opencode/scripts/setup-memory.sh
Sergey 7c1fa4985e
feat(memory): wire CLI into plugin via setup-memory.sh wrapper (#77)
* feat(memory): wire setup-memory.sh to Python CLI + JS wrapper

* test(memory): add wrapper generation, idempotency, backup tests

* docs(memory): update project map for setup-memory wrapper integration

* docs(handoff): add handoff and ADR-033 for plugin wiring

* docs(handoff): set PR number

* docs(handoff): fix Pending em-dash typo in PR#77 handoff

---------

Co-authored-by: opencode-agent <agent@opencode.local>
2026-07-26 17:06:45 +03:00

127 lines
No EOL
4.5 KiB
Bash
Executable file

#!/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)"