- Add `SEARCH_PROVIDER` config with Tavily/Brave API key validation in server and prod script - Introduce unified `web_search` tool and shared search service with Tavily + Brave backends - Update chat UI tool status/result labels to treat both search tools consistently
163 lines
5.2 KiB
Bash
Executable File
163 lines
5.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# GroupChat2 Production Build & Run Script
|
|
# Builds the client, compiles the server in release mode, and runs it.
|
|
# The Rust server serves the static client files directly — no Vite needed.
|
|
#
|
|
# Usage:
|
|
# ./prod.sh # Build + run
|
|
# ./prod.sh build # Build only (no run)
|
|
# ./prod.sh run # Run only (skip build, assumes already built)
|
|
|
|
set -e
|
|
|
|
ROOT="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
# Colors
|
|
MAGENTA='\033[0;35m'
|
|
YELLOW='\033[0;33m'
|
|
CYAN='\033[0;36m'
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
GRAY='\033[0;90m'
|
|
NC='\033[0m'
|
|
|
|
MODE="${1:-all}" # all | build | run
|
|
|
|
# ─── Preflight checks ───────────────────────────────────────────────
|
|
|
|
check_env() {
|
|
if [ ! -f "$ROOT/server/.env" ]; then
|
|
echo -e "${RED}[prod] Missing server/.env file!${NC}"
|
|
echo -e "${GRAY} Copy server/.env.example and fill in your keys:${NC}"
|
|
echo -e "${GRAY} cp server/.env.example server/.env${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
# Source .env to validate required vars
|
|
set -a
|
|
source "$ROOT/server/.env"
|
|
set +a
|
|
|
|
SEARCH_PROVIDER="${SEARCH_PROVIDER:-tavily}"
|
|
|
|
if [ -z "$OPENROUTER_API_KEY" ] || [ "$OPENROUTER_API_KEY" = "your-openrouter-api-key-here" ]; then
|
|
echo -e "${RED}[prod] OPENROUTER_API_KEY not set in server/.env${NC}"
|
|
exit 1
|
|
fi
|
|
if [ "$SEARCH_PROVIDER" = "tavily" ]; then
|
|
if [ -z "$TAVILY_API_KEY" ] || [ "$TAVILY_API_KEY" = "tvly-your-key-here" ]; then
|
|
echo -e "${RED}[prod] TAVILY_API_KEY not set in server/.env${NC}"
|
|
exit 1
|
|
fi
|
|
elif [ "$SEARCH_PROVIDER" = "brave" ]; then
|
|
if [ -z "$BRAVE_API_KEY" ] || [ "$BRAVE_API_KEY" = "your-brave-api-key-here" ]; then
|
|
echo -e "${RED}[prod] BRAVE_API_KEY not set in server/.env${NC}"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo -e "${RED}[prod] SEARCH_PROVIDER must be 'tavily' or 'brave'${NC}"
|
|
exit 1
|
|
fi
|
|
if [ -z "$JWT_SECRET" ] || [ "$JWT_SECRET" = "dev-secret-change-me" ]; then
|
|
echo -e "${YELLOW}[prod] WARNING: Using default JWT_SECRET — set a real secret for production!${NC}"
|
|
fi
|
|
}
|
|
|
|
# ─── Build ───────────────────────────────────────────────────────────
|
|
|
|
build() {
|
|
echo -e "${MAGENTA}[prod] Building GroupChat2 for production...${NC}"
|
|
echo ""
|
|
|
|
# 1. Install client deps if needed
|
|
if [ ! -d "$ROOT/client/node_modules" ]; then
|
|
echo -e "${CYAN}[prod] Installing client dependencies...${NC}"
|
|
(cd "$ROOT/client" && npm install)
|
|
fi
|
|
|
|
# 2. Build client (Vite → dist/)
|
|
echo -e "${CYAN}[prod] Building client...${NC}"
|
|
(cd "$ROOT/client" && npm run build)
|
|
echo -e "${GREEN}[prod] Client built → client/dist/${NC}"
|
|
|
|
# 3. Build server in release mode
|
|
echo -e "${YELLOW}[prod] Building server (release)...${NC}"
|
|
(cd "$ROOT/server" && cargo build --release)
|
|
echo -e "${GREEN}[prod] Server built → server/target/release/groupchat-server${NC}"
|
|
|
|
echo ""
|
|
echo -e "${GREEN}[prod] Build complete!${NC}"
|
|
}
|
|
|
|
# ─── Run ─────────────────────────────────────────────────────────────
|
|
|
|
run() {
|
|
check_env
|
|
|
|
# Verify build artifacts exist
|
|
if [ ! -f "$ROOT/server/target/release/groupchat-server" ]; then
|
|
echo -e "${RED}[prod] Server binary not found. Run './prod.sh build' first.${NC}"
|
|
exit 1
|
|
fi
|
|
if [ ! -d "$ROOT/client/dist" ]; then
|
|
echo -e "${RED}[prod] Client dist not found. Run './prod.sh build' first.${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
BIND_ADDR="${BIND_ADDR:-0.0.0.0:3001}"
|
|
|
|
echo ""
|
|
echo -e " ${MAGENTA}GroupChat2 Production${NC}"
|
|
echo -e " ${GREEN}Domain: https://gchat.tud.ink${NC}"
|
|
echo -e " ${YELLOW}Bind: ${BIND_ADDR}${NC}"
|
|
echo -e " ${GRAY}Press Ctrl+C to stop${NC}"
|
|
echo ""
|
|
|
|
# Source .env so the server binary picks up the vars
|
|
set -a
|
|
source "$ROOT/server/.env"
|
|
set +a
|
|
|
|
export STATIC_DIR="$ROOT/client/dist"
|
|
export BIND_ADDR
|
|
export RUST_LOG="${RUST_LOG:-info}"
|
|
|
|
cleanup() {
|
|
echo ""
|
|
echo -e "${RED}[prod] Shutting down...${NC}"
|
|
kill "$SERVER_PID" 2>/dev/null || true
|
|
lsof -ti:3001 2>/dev/null | xargs kill -9 2>/dev/null || true
|
|
echo -e "${RED}[prod] Stopped.${NC}"
|
|
exit 0
|
|
}
|
|
trap cleanup INT TERM
|
|
|
|
# Run the release binary
|
|
"$ROOT/server/target/release/groupchat-server" &
|
|
SERVER_PID=$!
|
|
|
|
wait "$SERVER_PID"
|
|
}
|
|
|
|
# ─── Main ────────────────────────────────────────────────────────────
|
|
|
|
case "$MODE" in
|
|
build)
|
|
build
|
|
;;
|
|
run)
|
|
run
|
|
;;
|
|
all|"")
|
|
build
|
|
run
|
|
;;
|
|
*)
|
|
echo "Usage: $0 [build|run]"
|
|
echo " (no args) Build and run"
|
|
echo " build Build only"
|
|
echo " run Run only (must build first)"
|
|
exit 1
|
|
;;
|
|
esac
|