feat: add git-consistent memory gateway architecture

This commit is contained in:
lingyuzeng
2026-03-07 22:33:41 +08:00
commit d4cd81f498
40 changed files with 2114 additions and 0 deletions

60
scripts/bootstrap.sh Executable file
View File

@@ -0,0 +1,60 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${ROOT_DIR}"
mkdir -p data/git-mirror data/workspaces data/qmd-cache data/qmd-config
REMOTE_BARE="${ROOT_DIR}/data/remote-memory.git"
if [[ ! -d "${REMOTE_BARE}" ]]; then
echo "[bootstrap] initializing demo remote repo at ${REMOTE_BARE}"
git init --bare "${REMOTE_BARE}"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "${tmp_dir}"' EXIT
git clone "${REMOTE_BARE}" "${tmp_dir}/seed"
git -C "${tmp_dir}/seed" config user.name "Memory Gateway Bot"
git -C "${tmp_dir}/seed" config user.email "memory-gateway@example.local"
mkdir -p "${tmp_dir}/seed/docs"
cat > "${tmp_dir}/seed/docs/main.md" <<'EOF'
# Main Memory
router firmware build recovery strategy in main branch.
EOF
git -C "${tmp_dir}/seed" add docs/main.md
git -C "${tmp_dir}/seed" commit -m "init main memory"
git -C "${tmp_dir}/seed" branch -M main
git -C "${tmp_dir}/seed" push -u origin main
git -C "${tmp_dir}/seed" checkout -b memory/2026-03
cat > "${tmp_dir}/seed/docs/monthly.md" <<'EOF'
# Monthly Memory 2026-03
monthly branch note for March 2026.
EOF
git -C "${tmp_dir}/seed" add docs/monthly.md
git -C "${tmp_dir}/seed" commit -m "add monthly memory"
git -C "${tmp_dir}/seed" push -u origin memory/2026-03
git -C "${tmp_dir}/seed" checkout -b task/TASK-001 main
cat > "${tmp_dir}/seed/docs/task-TASK-001.md" <<'EOF'
# Task Memory TASK-001
task specific recovery checkpoint.
EOF
git -C "${tmp_dir}/seed" add docs/task-TASK-001.md
git -C "${tmp_dir}/seed" commit -m "add task memory"
git -C "${tmp_dir}/seed" push -u origin task/TASK-001
fi
if [[ ! -f .env ]]; then
cp .env.example .env
sed -i "s|^GIT_REMOTE_URL=.*$|GIT_REMOTE_URL=/data/remote-memory.git|" .env
echo "[bootstrap] generated .env with local demo remote: /data/remote-memory.git"
fi
echo "[bootstrap] done"

4
scripts/entrypoint.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -euo pipefail
exec /app/scripts/qmd-entrypoint.sh "$@"

65
scripts/qmd-entrypoint.sh Executable file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env bash
set -euo pipefail
CACHE_HOME="${XDG_CACHE_HOME:-/var/lib/qmd/cache}"
CONFIG_HOME="${XDG_CONFIG_HOME:-/var/lib/qmd/config}"
PORT="${QMD_HTTP_PORT:-8181}"
INTERNAL_PORT="${QMD_INTERNAL_PORT:-8182}"
QMD_LLM_FILE="${QMD_LLM_FILE:-/usr/local/lib/node_modules/@tobilu/qmd/dist/llm.js}"
mkdir -p "${CACHE_HOME}/qmd" "${CONFIG_HOME}/qmd"
apply_model_overrides() {
if [[ -z "${QMD_EMBED_MODEL_URI:-}" && -z "${QMD_RERANK_MODEL_URI:-}" && -z "${QMD_GENERATE_MODEL_URI:-}" ]]; then
return 0
fi
if [[ ! -f "${QMD_LLM_FILE}" ]]; then
echo "WARN: llm.js not found at ${QMD_LLM_FILE}, skip model overrides." >&2
return 0
fi
QMD_LLM_FILE="${QMD_LLM_FILE}" node - <<'NODE'
const fs = require("fs");
const llmFile = process.env.QMD_LLM_FILE;
let src = fs.readFileSync(llmFile, "utf8");
const replacements = [
["DEFAULT_EMBED_MODEL", process.env.QMD_EMBED_MODEL_URI],
["DEFAULT_RERANK_MODEL", process.env.QMD_RERANK_MODEL_URI],
["DEFAULT_GENERATE_MODEL", process.env.QMD_GENERATE_MODEL_URI],
];
for (const [name, value] of replacements) {
if (!value) continue;
const pattern = new RegExp(`const ${name} = \\"[^\\"]+\\";`);
if (!pattern.test(src)) {
console.error(`WARN: failed to find ${name} in ${llmFile}`);
continue;
}
src = src.replace(pattern, `const ${name} = ${JSON.stringify(value)};`);
}
fs.writeFileSync(llmFile, src, "utf8");
NODE
}
apply_model_overrides
qmd mcp --http --port "${INTERNAL_PORT}" &
qmd_pid=$!
socat "TCP-LISTEN:${PORT},fork,reuseaddr,bind=0.0.0.0" "TCP6:[::1]:${INTERNAL_PORT}" &
proxy_pid=$!
cleanup() {
kill "${proxy_pid}" "${qmd_pid}" 2>/dev/null || true
wait "${proxy_pid}" "${qmd_pid}" 2>/dev/null || true
}
trap cleanup SIGINT SIGTERM
wait -n "${qmd_pid}" "${proxy_pid}"
status=$?
cleanup
exit "${status}"

29
scripts/smoke-test.sh Executable file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${ROOT_DIR}"
log() {
printf '[smoke] %s\n' "$*"
}
log "Bootstrapping demo repo"
./scripts/bootstrap.sh
log "Starting services"
docker compose up -d --build
log "Checking health"
curl -fsS http://127.0.0.1:8181/health >/dev/null
curl -fsS http://127.0.0.1:8787/health >/dev/null
log "Running query through memory-gateway"
query_output="$(curl -fsS -X POST http://127.0.0.1:8787/query \
-H 'content-type: application/json' \
-d '{"branch":"main","query_type":"search","query":"router","require_latest":true,"debug":true}')"
printf '%s\n' "${query_output}"
printf '%s\n' "${query_output}" | grep -F 'commit_hash' >/dev/null
printf '%s\n' "${query_output}" | grep -F 'branch' >/dev/null
log "Smoke test passed"

27
scripts/warmup.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "${ROOT_DIR}"
BASE_URL="${GATEWAY_BASE_URL:-http://127.0.0.1:8787}"
wait_health() {
local attempts=60
for _ in $(seq 1 "${attempts}"); do
if curl -fsS "${BASE_URL}/health" >/dev/null 2>&1; then
return 0
fi
sleep 2
done
echo "ERROR: gateway did not become healthy at ${BASE_URL}/health" >&2
return 1
}
wait_health
curl -fsS -X POST "${BASE_URL}/query" \
-H 'content-type: application/json' \
-d '{"branch":"main","query_type":"search","query":"router","require_latest":true,"debug":true}' >/dev/null
echo "Warmup completed."