#!/usr/bin/env bash set -euo pipefail REPO_DIR="$(cd "$(dirname "$0")" && pwd)" ENV_FILE="$REPO_DIR/.env" PID_FILE="$REPO_DIR/data/sparrow.pid" FE_PID_FILE="$REPO_DIR/data/sparrow-fe.pid" LOG_FILE="$REPO_DIR/data/sparrow.log" FE_LOG_FILE="$REPO_DIR/data/sparrow-fe.log" [[ -f "$ENV_FILE" ]] && { set -a; source "$ENV_FILE"; set +a; } SPARROW_PORT="${SPARROW_PORT:-8513}" SPARROW_FE_PORT="${SPARROW_FE_PORT:-8514}" cmd="${1:-help}" _running() { [[ -f "$1" ]] && kill -0 "$(cat "$1")" 2>/dev/null; } start_api() { mkdir -p "$REPO_DIR/data" if _running "$PID_FILE"; then echo "API already running (PID $(cat "$PID_FILE"))" return fi echo "Starting Sparrow API on port $SPARROW_PORT..." conda run -n cf \ uvicorn app.main:app --host "${SPARROW_HOST:-0.0.0.0}" --port "$SPARROW_PORT" \ >> "$LOG_FILE" 2>&1 & echo $! > "$PID_FILE" echo "API started (PID $!). Logs: $LOG_FILE" } stop_api() { if [[ -f "$PID_FILE" ]]; then kill "$(cat "$PID_FILE")" 2>/dev/null && echo "API stopped." || echo "API not running." rm -f "$PID_FILE" else echo "API not running." fi } start_fe() { mkdir -p "$REPO_DIR/data" if _running "$FE_PID_FILE"; then echo "Frontend already running (PID $(cat "$FE_PID_FILE"))" return fi echo "Starting Sparrow frontend on port $SPARROW_FE_PORT..." (cd "$REPO_DIR/frontend" && npm run dev -- --port "$SPARROW_FE_PORT" --host 0.0.0.0) \ >> "$FE_LOG_FILE" 2>&1 & echo $! > "$FE_PID_FILE" echo "Frontend started (PID $!). Logs: $FE_LOG_FILE" } stop_fe() { if [[ -f "$FE_PID_FILE" ]]; then kill "$(cat "$FE_PID_FILE")" 2>/dev/null && echo "Frontend stopped." || echo "Frontend not running." rm -f "$FE_PID_FILE" else echo "Frontend not running." fi } case "$cmd" in start) start_api start_fe ;; stop) stop_api stop_fe ;; restart) stop_api; stop_fe; sleep 1; start_api; start_fe ;; start-api) start_api ;; stop-api) stop_api ;; start-fe) start_fe ;; stop-fe) stop_fe ;; status) _running "$PID_FILE" && echo "API: running (PID $(cat "$PID_FILE"))" || echo "API: stopped" _running "$FE_PID_FILE" && echo "Frontend: running (PID $(cat "$FE_PID_FILE"))" || echo "Frontend: stopped" ;; logs) echo "=== API ===" && tail -40 "$LOG_FILE" 2>/dev/null || true echo "=== Frontend ===" && tail -20 "$FE_LOG_FILE" 2>/dev/null || true ;; open) xdg-open "http://localhost:$SPARROW_FE_PORT" 2>/dev/null || \ open "http://localhost:$SPARROW_FE_PORT" 2>/dev/null || true ;; test) cd "$REPO_DIR" && conda run -n cf python -m pytest tests/ -v "$@" ;; *) echo "Usage: $0 {start|stop|restart|status|logs|open|test}" echo " $0 {start-api|stop-api|start-fe|stop-fe}" ;; esac