mirror of
https://github.com/NVIDIA/dgx-spark-playbooks.git
synced 2026-06-22 14:19:30 +00:00
217 lines
8.4 KiB
Bash
217 lines
8.4 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Verify sandbox config matches the repo.
|
|
# Catches stale skills, missing files, broken imports, and memory errors.
|
|
#
|
|
# Usage:
|
|
# bash scripts/check_sandbox_config.sh [sandbox-name]
|
|
#
|
|
# Returns exit code 0 if all checks pass, 1 if any fail.
|
|
|
|
set -uo pipefail
|
|
|
|
SANDBOX="${1:-clinical-sandbox}"
|
|
REPO_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
FAIL=0
|
|
WARN=0
|
|
|
|
green() { printf "\033[32m✓ %s\033[0m\n" "$1"; }
|
|
red() { printf "\033[31m✗ %s\033[0m\n" "$1"; FAIL=$((FAIL+1)); }
|
|
yellow(){ printf "\033[33m⚠ %s\033[0m\n" "$1"; WARN=$((WARN+1)); }
|
|
|
|
sandbox_exec() {
|
|
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
|
|
-o LogLevel=ERROR -o ConnectTimeout=15 \
|
|
-o "ProxyCommand=openshell ssh-proxy --gateway-name openshell --name ${SANDBOX}" \
|
|
"sandbox@openshell-${SANDBOX}" "$1" 2>/dev/null
|
|
}
|
|
|
|
echo "=== Sandbox Config Check: ${SANDBOX} ==="
|
|
echo ""
|
|
|
|
# ── 1. Sandbox exists and is ready ─────────────────────────────
|
|
echo "--- Sandbox Status ---"
|
|
PHASE=$(openshell sandbox list 2>/dev/null | grep "$SANDBOX" | awk '{print $NF}' | sed 's/\x1b\[[0-9;]*m//g')
|
|
if [ "$PHASE" = "Ready" ]; then
|
|
green "Sandbox $SANDBOX is Ready"
|
|
else
|
|
red "Sandbox $SANDBOX is not Ready (phase: ${PHASE:-not found})"
|
|
echo " Run: make setup"
|
|
exit 1
|
|
fi
|
|
|
|
# ── 2. Collect all hashes from sandbox in one SSH call ─────────
|
|
echo ""
|
|
echo "--- Collecting sandbox state (one SSH call) ---"
|
|
SANDBOX_STATE=$(sandbox_exec '
|
|
echo "=== HASHES ==="
|
|
for f in \
|
|
~/.openclaw/agents/main/agent/IDENTITY.md \
|
|
~/.openclaw/workspace/IDENTITY.md \
|
|
~/.openclaw/workspace/skills/fhir-basics/SKILL.md \
|
|
~/.openclaw/workspace/skills/analysis-methods/SKILL.md \
|
|
~/.openclaw/workspace/skills/clinical-knowledge/SKILL.md \
|
|
~/.openclaw/workspace/skills/cohort-compare/SKILL.md \
|
|
~/.openclaw/workspace/skills/case-summary/SKILL.md \
|
|
~/.openclaw/workspace/skills/clinical-delegation/SKILL.md \
|
|
~/.openclaw/workspace/skills/molecular-viz/SKILL.md; do
|
|
if [ -f "$f" ]; then
|
|
md5sum "$f"
|
|
else
|
|
echo "MISSING $f"
|
|
fi
|
|
done
|
|
echo "=== HELPERS ==="
|
|
if [ -f /sandbox/clinical-intelligence/skills/analysis-methods/scripts/fhir_helpers.py ]; then
|
|
echo "HELPERS_EXISTS"
|
|
python3 -c "import sys; sys.path.insert(0, \"/sandbox/clinical-intelligence/skills/analysis-methods/scripts\"); from fhir_helpers import fhir_get; print(\"IMPORT_OK\")" 2>&1
|
|
else
|
|
echo "HELPERS_MISSING"
|
|
fi
|
|
echo "=== MEMORY ==="
|
|
[ -d ~/.openclaw/workspace/memory ] && echo "MEMORY_DIR_EXISTS" || echo "MEMORY_DIR_MISSING"
|
|
[ -f ~/.openclaw/workspace/MEMORY.md ] && echo "MEMORY_FILE_EXISTS" || echo "MEMORY_FILE_MISSING"
|
|
echo "=== GATEWAY ==="
|
|
curl -sf http://127.0.0.1:18789/ >/dev/null 2>&1 && echo "GATEWAY_UP" || echo "GATEWAY_DOWN"
|
|
echo "=== AGENTS ==="
|
|
openclaw agents list 2>/dev/null | grep -c "^\- " || echo "0"
|
|
echo "=== INFERENCE ==="
|
|
curl -sf https://inference.local/v1/models 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[\"data\"][0][\"id\"])" 2>/dev/null || echo "INFERENCE_FAIL"
|
|
echo "=== NESTED ==="
|
|
[ -d /sandbox/clinical-intelligence/skills/analysis-methods/analysis-methods ] && echo "NESTED_YES" || echo "NESTED_NO"
|
|
')
|
|
|
|
if [ -z "$SANDBOX_STATE" ]; then
|
|
red "Could not connect to sandbox"
|
|
exit 1
|
|
fi
|
|
|
|
# ── 3. Parse and check IDENTITY.md ─────────────────────────────
|
|
echo ""
|
|
echo "--- IDENTITY.md ---"
|
|
REPO_ID_HASH=$(md5sum "$REPO_DIR/IDENTITY.md" 2>/dev/null | awk '{print $1}')
|
|
AGENT_ID_HASH=$(echo "$SANDBOX_STATE" | grep "agents/main/agent/IDENTITY.md" | awk '{print $1}')
|
|
WORKSPACE_ID_HASH=$(echo "$SANDBOX_STATE" | grep "workspace/IDENTITY.md" | head -1 | awk '{print $1}')
|
|
|
|
if [ "$REPO_ID_HASH" = "$AGENT_ID_HASH" ]; then
|
|
green "Agent IDENTITY.md matches repo"
|
|
else
|
|
red "Agent IDENTITY.md is STALE (repo: ${REPO_ID_HASH:0:8} sandbox: ${AGENT_ID_HASH:0:8})"
|
|
fi
|
|
|
|
if [ "$REPO_ID_HASH" = "$WORKSPACE_ID_HASH" ]; then
|
|
green "Workspace IDENTITY.md matches repo"
|
|
else
|
|
red "Workspace IDENTITY.md is STALE (repo: ${REPO_ID_HASH:0:8} workspace: ${WORKSPACE_ID_HASH:0:8})"
|
|
fi
|
|
|
|
# ── 4. Check each skill ───────────────────────────────────────
|
|
echo ""
|
|
echo "--- Skills ---"
|
|
for skill_dir in "$REPO_DIR"/skills/*/; do
|
|
skill_name=$(basename "$skill_dir")
|
|
REPO_HASH=$(md5sum "$skill_dir/SKILL.md" 2>/dev/null | awk '{print $1}')
|
|
SANDBOX_LINE=$(echo "$SANDBOX_STATE" | grep "workspace/skills/$skill_name/SKILL.md")
|
|
|
|
if echo "$SANDBOX_LINE" | grep -q "MISSING"; then
|
|
red "Skill $skill_name: NOT FOUND in workspace"
|
|
else
|
|
SANDBOX_HASH=$(echo "$SANDBOX_LINE" | awk '{print $1}')
|
|
if [ "$REPO_HASH" = "$SANDBOX_HASH" ]; then
|
|
green "Skill $skill_name matches repo"
|
|
else
|
|
red "Skill $skill_name is STALE (repo: ${REPO_HASH:0:8} workspace: ${SANDBOX_HASH:0:8})"
|
|
fi
|
|
fi
|
|
done
|
|
|
|
# ── 5. Helpers ─────────────────────────────────────────────────
|
|
echo ""
|
|
echo "--- Helper Scripts ---"
|
|
if echo "$SANDBOX_STATE" | grep -q "HELPERS_EXISTS"; then
|
|
green "fhir_helpers.py exists"
|
|
else
|
|
red "fhir_helpers.py MISSING"
|
|
fi
|
|
|
|
if echo "$SANDBOX_STATE" | grep -q "IMPORT_OK"; then
|
|
green "fhir_helpers.py imports OK"
|
|
else
|
|
red "fhir_helpers.py import FAILED"
|
|
fi
|
|
|
|
# ── 6. Memory ──────────────────────────────────────────────────
|
|
echo ""
|
|
echo "--- Memory ---"
|
|
if echo "$SANDBOX_STATE" | grep -q "MEMORY_DIR_EXISTS"; then
|
|
green "memory/ directory exists"
|
|
else
|
|
red "memory/ directory MISSING (causes ENOENT on session start)"
|
|
fi
|
|
|
|
if echo "$SANDBOX_STATE" | grep -q "MEMORY_FILE_EXISTS"; then
|
|
green "MEMORY.md exists"
|
|
else
|
|
red "MEMORY.md MISSING"
|
|
fi
|
|
|
|
# ── 7. Gateway ─────────────────────────────────────────────────
|
|
echo ""
|
|
echo "--- OpenClaw Gateway ---"
|
|
if echo "$SANDBOX_STATE" | grep -q "GATEWAY_UP"; then
|
|
green "OpenClaw gateway responding"
|
|
else
|
|
red "OpenClaw gateway DOWN"
|
|
echo " Fix: make restart"
|
|
fi
|
|
|
|
# ── 8. Agents ──────────────────────────────────────────────────
|
|
echo ""
|
|
echo "--- Agents ---"
|
|
AGENT_COUNT=$(echo "$SANDBOX_STATE" | sed -n '/=== AGENTS ===/,/=== INFERENCE ===/p' | grep -v '===' | head -1 | tr -d '[:space:]')
|
|
if [ "${AGENT_COUNT:-0}" -ge 6 ]; then
|
|
green "$AGENT_COUNT agents registered"
|
|
else
|
|
red "Only ${AGENT_COUNT:-0} agents (expected 6)"
|
|
fi
|
|
|
|
# ── 9. Inference ───────────────────────────────────────────────
|
|
echo ""
|
|
echo "--- Inference ---"
|
|
INFERENCE_MODEL=$(echo "$SANDBOX_STATE" | sed -n '/=== INFERENCE ===/,/=== NESTED ===/p' | grep -v '===' | head -1)
|
|
if echo "$INFERENCE_MODEL" | grep -q "nemotron"; then
|
|
green "Inference: $INFERENCE_MODEL"
|
|
else
|
|
red "Inference FAILED (got: ${INFERENCE_MODEL:-nothing})"
|
|
fi
|
|
|
|
# ── 10. Port forward ──────────────────────────────────────────
|
|
echo ""
|
|
echo "--- Port Forward ---"
|
|
FWD_STATUS=$(openshell forward list 2>/dev/null | grep "$SANDBOX" | sed 's/\x1b\[[0-9;]*m//g' | grep -o 'running\|dead')
|
|
if [ "$FWD_STATUS" = "running" ]; then
|
|
green "Port forward 18789 running"
|
|
else
|
|
red "Port forward 18789 ${FWD_STATUS:-not found}"
|
|
fi
|
|
|
|
# ── 11. Nested directories ────────────────────────────────────
|
|
echo ""
|
|
echo "--- Directory Structure ---"
|
|
if echo "$SANDBOX_STATE" | grep -q "NESTED_YES"; then
|
|
red "Nested analysis-methods/analysis-methods/ directory found"
|
|
else
|
|
green "No nested directory issues"
|
|
fi
|
|
|
|
# ── Summary ────────────────────────────────────────────────────
|
|
echo ""
|
|
echo "=== Summary ==="
|
|
if [ $FAIL -eq 0 ]; then
|
|
green "All checks passed ($WARN warning(s))"
|
|
exit 0
|
|
else
|
|
red "$FAIL check(s) FAILED, $WARN warning(s)"
|
|
exit 1
|
|
fi
|