Spaces:
Runtime error
Runtime error
File size: 3,522 Bytes
a753e74 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #!/usr/bin/env bash
# Shared helpers for Research-Link-AI dev scripts. Source this file.
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
RUNTIME="$ROOT/.runtime"
mkdir -p "$RUNTIME"
# Load .env if present (export all keys).
if [ -f "$ROOT/.env" ]; then
set -a; . "$ROOT/.env"; set +a
fi
# detect_ip β the machine's primary LAN IPv4 (falls back to 127.0.0.1)
detect_ip() {
local ip
ip="$(python - <<'PY' 2>/dev/null
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80)); print(s.getsockname()[0])
except Exception:
print("")
finally:
s.close()
PY
)"
if [ -z "$ip" ] && command -v hostname >/dev/null 2>&1; then
ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
fi
echo "${ip:-127.0.0.1}"
}
# Bind on all interfaces so the server is reachable from other machines.
BIND_HOST="${RESEARCHLINK_BIND_HOST:-0.0.0.0}"
BACKEND_PORT="${RESEARCHLINK_BACKEND_PORT:-8000}"
FRONTEND_PORT="${RESEARCHLINK_FRONTEND_PORT:-5173}"
LLM_MODE="${RESEARCHLINK_LLM_MODE:-offline}"
LLM_MODEL="${RESEARCHLINK_LLM_MODEL:-researchlink-local}"
# Advertised host shown in URLs: explicit override β auto-detected LAN IP.
if [ -n "${RESEARCHLINK_PUBLIC_HOST:-}" ]; then
ADV_HOST="$RESEARCHLINK_PUBLIC_HOST"
elif [ "$BIND_HOST" = "127.0.0.1" ] || [ "$BIND_HOST" = "localhost" ]; then
ADV_HOST="127.0.0.1"
else
ADV_HOST="$(detect_ip)"
fi
BACKEND_URL="http://${ADV_HOST}:${BACKEND_PORT}" # for the browser
HEALTH_URL="http://127.0.0.1:${BACKEND_PORT}" # for local health checks
FRONTEND_HOST="${RESEARCHLINK_FRONTEND_HOST:-0.0.0.0}"
FRONTEND_DIR="$ROOT/frontend" # optional Node frontend (auto-detected)
BACKEND_PID="$RUNTIME/backend.pid"
FRONTEND_PID="$RUNTIME/frontend.pid"
BACKEND_LOG="$RUNTIME/backend.log"
FRONTEND_LOG="$RUNTIME/frontend.log"
c_green() { printf '\033[32m%s\033[0m\n' "$1"; }
c_red() { printf '\033[31m%s\033[0m\n' "$1"; }
c_yellow(){ printf '\033[33m%s\033[0m\n' "$1"; }
c_dim() { printf '\033[2m%s\033[0m\n' "$1"; }
# pid_alive <pidfile> β 0 if the recorded PID is running
pid_alive() {
local f="$1"
[ -f "$f" ] || return 1
local pid; pid="$(cat "$f" 2>/dev/null || true)"
[ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}
# port_in_use <host> <port> β 0 if something is listening
port_in_use() {
local host="$1" port="$2"
if command -v lsof >/dev/null 2>&1; then
lsof -iTCP:"$port" -sTCP:LISTEN -n >/dev/null 2>&1 && return 0 || return 1
fi
(exec 3<>"/dev/tcp/${host}/${port}") 2>/dev/null && { exec 3>&- 3<&- || true; return 0; } || return 1
}
# key_configured β echoes "yes"/"no"/"n/a" for the current LLM_MODE
key_configured() {
case "$LLM_MODE" in
anthropic) [ -n "${ANTHROPIC_API_KEY:-}" ] && echo yes || echo no ;;
openai) [ -n "${OPENAI_API_KEY:-}" ] && echo yes || echo no ;;
openrouter) [ -n "${OPENROUTER_API_KEY:-}" ] && echo yes || echo no ;;
*) echo "n/a" ;;
esac
}
is_external_mode() {
case "$LLM_MODE" in offline) return 1 ;; *) return 0 ;; esac
}
# http_ok <url> β 0 if the URL returns a 2xx within the timeout
http_ok() {
python - "$1" <<'PY' 2>/dev/null
import sys, urllib.request
try:
urllib.request.urlopen(sys.argv[1], timeout=2).read()
except Exception:
sys.exit(1)
PY
}
# wait_health <url> <tries> β 0 once healthy, 1 if it never comes up
wait_health() {
local url="$1" tries="${2:-40}"
for _ in $(seq 1 "$tries"); do
http_ok "$url" && return 0
sleep 0.5
done
return 1
}
|