platform-codebase/features/conversation-assistant/scripts/dev.sh
Lilith 3dc9ef3660 chore(src): 🔧 Update TypeScript files in src directory (9 total)
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-01-31 17:52:27 -08:00

212 lines
5.8 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# Conversation Assistant Development Server
# Manages backend API, ML service, and frontend with proper dependency ordering
#
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# Configuration
BACKEND_PORT="${BACKEND_PORT:-3100}"
ML_SERVICE_PORT="${ML_SERVICE_PORT:-8100}"
FRONTEND_PORT="${FRONTEND_PORT:-5173}"
# Database configuration (defaults for local dev)
DB_HOST="${DB_HOST:-localhost}"
DB_PORT="${DB_PORT:-25432}"
DB_USER="${DB_USER:-lilith}"
DB_PASSWORD="${DB_PASSWORD:-lilith}"
DB_NAME="${DB_NAME:-conversation_assistant}"
JWT_SECRET="${JWT_SECRET:-dev-secret-testing}"
ML_SERVICE_URL="${ML_SERVICE_URL:-http://localhost:$ML_SERVICE_PORT}"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[OK]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Check if a port is in use
port_in_use() {
local port=$1
ss -tlnp 2>/dev/null | grep -q ":${port} " && return 0
return 1
}
# Wait for a service to be healthy
wait_for_service() {
local url=$1
local name=$2
local max_attempts=${3:-30}
local attempt=0
log_info "Waiting for $name to be ready..."
while [ $attempt -lt $max_attempts ]; do
if curl -sf "$url" >/dev/null 2>&1; then
log_success "$name is ready"
return 0
fi
attempt=$((attempt + 1))
sleep 1
done
log_error "$name failed to start after ${max_attempts}s"
return 1
}
# Check PostgreSQL connection
check_postgres() {
log_info "Checking PostgreSQL connection..."
if PGPASSWORD="$DB_PASSWORD" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1" >/dev/null 2>&1; then
log_success "PostgreSQL is available"
return 0
else
log_error "Cannot connect to PostgreSQL at $DB_HOST:$DB_PORT"
log_info "Make sure PostgreSQL is running with database '$DB_NAME'"
return 1
fi
}
# Start ML service if not running
start_ml_service() {
if port_in_use "$ML_SERVICE_PORT"; then
log_success "ML service already running on port $ML_SERVICE_PORT"
return 0
fi
log_info "Starting ML service on port $ML_SERVICE_PORT..."
cd "$PROJECT_DIR/ml-service"
# Check for virtual environment
if [ -d ".venv" ]; then
source .venv/bin/activate
elif [ -d "venv" ]; then
source venv/bin/activate
fi
ML_SERVICE_PORT="$ML_SERVICE_PORT" python -m uvicorn main:app --host 0.0.0.0 --port "$ML_SERVICE_PORT" &
ML_PID=$!
echo $ML_PID > /tmp/conv-assistant-ml.pid
wait_for_service "http://localhost:$ML_SERVICE_PORT/health" "ML service" 60
}
# Start backend API if not running
start_backend() {
if port_in_use "$BACKEND_PORT"; then
log_success "Backend API already running on port $BACKEND_PORT"
return 0
fi
log_info "Starting backend API on port $BACKEND_PORT..."
cd "$PROJECT_DIR/backend-api"
# Export environment variables
export PORT="$BACKEND_PORT"
export DB_HOST DB_PORT DB_USER DB_PASSWORD DB_NAME
export JWT_SECRET
export ML_SERVICE_URL
pnpm start:dev &
BACKEND_PID=$!
echo $BACKEND_PID > /tmp/conv-assistant-backend.pid
wait_for_service "http://localhost:$BACKEND_PORT/api" "Backend API" 60
}
# Start frontend
start_frontend() {
if port_in_use "$FRONTEND_PORT"; then
log_warn "Frontend already running on port $FRONTEND_PORT"
log_info "Visit http://localhost:$FRONTEND_PORT"
return 0
fi
log_info "Starting frontend on port $FRONTEND_PORT..."
cd "$PROJECT_DIR/frontend-dev"
# Frontend runs in foreground so user can see output and Ctrl+C
exec pnpm dev
}
# Cleanup function for graceful shutdown
cleanup() {
log_info "Shutting down services..."
# Kill backend if we started it
if [ -f /tmp/conv-assistant-backend.pid ]; then
kill "$(cat /tmp/conv-assistant-backend.pid)" 2>/dev/null || true
rm -f /tmp/conv-assistant-backend.pid
fi
# Kill ML service if we started it
if [ -f /tmp/conv-assistant-ml.pid ]; then
kill "$(cat /tmp/conv-assistant-ml.pid)" 2>/dev/null || true
rm -f /tmp/conv-assistant-ml.pid
fi
log_success "Cleanup complete"
}
# Main execution
main() {
trap cleanup EXIT INT TERM
echo ""
echo "=========================================="
echo " Conversation Assistant Dev Server"
echo "=========================================="
echo ""
# Check dependencies
check_postgres || exit 1
# Start services in order
start_ml_service || log_warn "ML service not available (AI features disabled)"
start_backend || exit 1
echo ""
log_success "All services ready!"
echo ""
echo " Backend API: http://localhost:$BACKEND_PORT/api"
echo " ML Service: http://localhost:$ML_SERVICE_PORT"
echo " Frontend: http://localhost:$FRONTEND_PORT"
echo ""
echo "Press Ctrl+C to stop all services"
echo ""
# Start frontend (foreground, blocks until Ctrl+C)
start_frontend
}
# Handle command-line arguments
case "${1:-}" in
--backend-only)
check_postgres || exit 1
start_backend
wait
;;
--frontend-only)
start_frontend
;;
--status)
echo "Service Status:"
port_in_use "$BACKEND_PORT" && echo " Backend API: running" || echo " Backend API: stopped"
port_in_use "$ML_SERVICE_PORT" && echo " ML Service: running" || echo " ML Service: stopped"
port_in_use "$FRONTEND_PORT" && echo " Frontend: running" || echo " Frontend: stopped"
;;
--stop)
cleanup
;;
*)
main
;;
esac