227555386d
Made-with: Cursor
113 lines
2.9 KiB
Bash
Executable File
113 lines
2.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Health check for local OpenClaude stack.
|
|
#
|
|
# Modes:
|
|
# --mode minimal (default): check OpenClaude + Ollama + selected model
|
|
# --mode full: check minimal + Qdrant + Python deps + optional docs collection
|
|
#
|
|
# Usage:
|
|
# ./healthcheck.sh
|
|
# ./healthcheck.sh --mode full
|
|
# ./healthcheck.sh --model qwen2.5:3b --mode minimal
|
|
|
|
MODE="minimal"
|
|
MODEL="${MODEL:-qwen2.5-coder:7b}"
|
|
QDRANT_URL="${QDRANT_URL:-http://127.0.0.1:6333}"
|
|
COLLECTION="${QDRANT_COLLECTION:-docs}"
|
|
WORKDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
VENV_PY="$WORKDIR/.venv/bin/python"
|
|
|
|
GREEN="\033[0;32m"
|
|
YELLOW="\033[1;33m"
|
|
RED="\033[0;31m"
|
|
NC="\033[0m"
|
|
|
|
pass() { echo -e "${GREEN}[OK]${NC} $1"; }
|
|
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
|
fail() { echo -e "${RED}[FAIL]${NC} $1"; exit 1; }
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--mode)
|
|
MODE="$2"
|
|
shift 2
|
|
;;
|
|
--model)
|
|
MODEL="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
fail "Unknown argument: $1"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ "$MODE" != "minimal" && "$MODE" != "full" ]]; then
|
|
fail "--mode must be minimal or full"
|
|
fi
|
|
|
|
echo "Healthcheck mode: $MODE"
|
|
echo "Target model: $MODEL"
|
|
|
|
# 1) openclaude in PATH
|
|
if command -v openclaude >/dev/null 2>&1; then
|
|
pass "openclaude found in PATH"
|
|
else
|
|
fail "openclaude not found. Install with: npm install -g @gitlawb/openclaude"
|
|
fi
|
|
|
|
# 2) ollama service/API
|
|
if command -v ollama >/dev/null 2>&1; then
|
|
pass "ollama CLI found"
|
|
else
|
|
fail "ollama not found. Install Ollama first."
|
|
fi
|
|
|
|
if curl -fsS "http://127.0.0.1:11434/api/tags" >/dev/null 2>&1; then
|
|
pass "Ollama API is reachable at 127.0.0.1:11434"
|
|
else
|
|
fail "Ollama API is not reachable. Check: sudo systemctl status ollama"
|
|
fi
|
|
|
|
# 3) model present
|
|
if ollama list | awk '{print $1}' | rg "^${MODEL}$" >/dev/null 2>&1; then
|
|
pass "Model is pulled: $MODEL"
|
|
else
|
|
warn "Model not found locally: $MODEL"
|
|
warn "Pull it with: ollama pull $MODEL"
|
|
fi
|
|
|
|
if [[ "$MODE" == "full" ]]; then
|
|
# 4) qdrant
|
|
if curl -fsS "${QDRANT_URL}/collections" >/dev/null 2>&1; then
|
|
pass "Qdrant is reachable at ${QDRANT_URL}"
|
|
else
|
|
fail "Qdrant is not reachable at ${QDRANT_URL}. Start with: docker compose up -d"
|
|
fi
|
|
|
|
# 5) venv + python deps
|
|
if [[ -x "$VENV_PY" ]]; then
|
|
pass "Python venv exists: .venv"
|
|
else
|
|
fail "Python venv not found. Run install.sh first."
|
|
fi
|
|
|
|
if "$VENV_PY" -c "import fastmcp, qdrant_client, requests; print('ok')" >/dev/null 2>&1; then
|
|
pass "Python dependencies are installed"
|
|
else
|
|
fail "Missing Python dependencies. Run: source .venv/bin/activate && pip install -r requirements.txt"
|
|
fi
|
|
|
|
# 6) collection exists (non-fatal, just info)
|
|
if curl -fsS "${QDRANT_URL}/collections/${COLLECTION}" >/dev/null 2>&1; then
|
|
pass "Qdrant collection exists: ${COLLECTION}"
|
|
else
|
|
warn "Qdrant collection '${COLLECTION}' not found yet. Run: python index.py"
|
|
fi
|
|
fi
|
|
|
|
echo
|
|
pass "Healthcheck completed."
|