Files
wifi-densepose/vendor/ruvector/npm/packages/ruvbot/scripts/install.sh

739 lines
20 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# RuvBot Installer
#
# Usage:
# curl -fsSL https://get.ruvector.dev/ruvbot | bash
# curl -fsSL https://raw.githubusercontent.com/ruvnet/ruvector/main/npm/packages/ruvbot/scripts/install.sh | bash
#
# Options (via environment variables):
# RUVBOT_VERSION - Specific version to install (default: latest)
# RUVBOT_GLOBAL - Install globally (default: true)
# RUVBOT_INIT - Run init after install (default: false)
# RUVBOT_CHANNEL - Configure channel: slack, discord, telegram
# RUVBOT_DEPLOY - Deploy target: local, docker, cloudrun, k8s
# RUVBOT_WIZARD - Run interactive wizard (default: false)
#
# Examples:
# # Basic install
# curl -fsSL https://get.ruvector.dev/ruvbot | bash
#
# # Install specific version
# RUVBOT_VERSION=0.1.3 curl -fsSL https://get.ruvector.dev/ruvbot | bash
#
# # Install and initialize
# RUVBOT_INIT=true curl -fsSL https://get.ruvector.dev/ruvbot | bash
#
# # Install with Slack configuration
# RUVBOT_CHANNEL=slack curl -fsSL https://get.ruvector.dev/ruvbot | bash
#
# # Install and deploy to Cloud Run
# RUVBOT_DEPLOY=cloudrun curl -fsSL https://get.ruvector.dev/ruvbot | bash
#
# # Run full interactive wizard
# RUVBOT_WIZARD=true curl -fsSL https://get.ruvector.dev/ruvbot | bash
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m' # No Color
BOLD='\033[1m'
DIM='\033[2m'
# Configuration
RUVBOT_VERSION="${RUVBOT_VERSION:-latest}"
RUVBOT_GLOBAL="${RUVBOT_GLOBAL:-true}"
RUVBOT_INIT="${RUVBOT_INIT:-false}"
RUVBOT_CHANNEL="${RUVBOT_CHANNEL:-}"
RUVBOT_DEPLOY="${RUVBOT_DEPLOY:-}"
RUVBOT_WIZARD="${RUVBOT_WIZARD:-false}"
# Feature flags
GCLOUD_AVAILABLE=false
DOCKER_AVAILABLE=false
KUBECTL_AVAILABLE=false
# Banner
print_banner() {
echo -e "${CYAN}"
echo ' ____ ____ _ '
echo ' | _ \ _ ___ _| __ ) ___ | |_ '
echo ' | |_) | | | \ \ / / _ \ / _ \| __|'
echo ' | _ <| |_| |\ V /| |_) | (_) | |_ '
echo ' |_| \_\\__,_| \_/ |____/ \___/ \__|'
echo -e "${NC}"
echo -e "${BOLD}Enterprise-Grade Self-Learning AI Assistant${NC}"
echo -e "${DIM}Military-strength security • 150x faster search • 12+ LLM models${NC}"
echo ""
}
# Logging functions
info() { echo -e "${BLUE}${NC} $1"; }
success() { echo -e "${GREEN}${NC} $1"; }
warn() { echo -e "${YELLOW}${NC} $1"; }
error() { echo -e "${RED}${NC} $1"; exit 1; }
step() { echo -e "\n${MAGENTA}${NC} ${BOLD}$1${NC}"; }
# Check dependencies
check_dependencies() {
step "Checking dependencies"
# Check Node.js
if ! command -v node &> /dev/null; then
error "Node.js is required but not installed. Install from https://nodejs.org"
fi
NODE_VERSION=$(node -v | cut -d 'v' -f 2 | cut -d '.' -f 1)
if [ "$NODE_VERSION" -lt 18 ]; then
error "Node.js 18+ is required. Current: $(node -v)"
fi
success "Node.js $(node -v)"
# Check npm
if ! command -v npm &> /dev/null; then
error "npm is required but not installed"
fi
success "npm $(npm -v)"
# Check optional: gcloud
if command -v gcloud &> /dev/null; then
success "gcloud CLI $(gcloud --version 2>/dev/null | head -1 | awk '{print $4}')"
GCLOUD_AVAILABLE=true
else
echo -e "${DIM} ○ gcloud CLI not found (optional for Cloud Run)${NC}"
fi
# Check optional: docker
if command -v docker &> /dev/null; then
success "Docker $(docker --version | awk '{print $3}' | tr -d ',')"
DOCKER_AVAILABLE=true
else
echo -e "${DIM} ○ Docker not found (optional for containerization)${NC}"
fi
# Check optional: kubectl
if command -v kubectl &> /dev/null; then
success "kubectl $(kubectl version --client -o json 2>/dev/null | grep -o '"gitVersion": "[^"]*"' | cut -d'"' -f4)"
KUBECTL_AVAILABLE=true
else
echo -e "${DIM} ○ kubectl not found (optional for Kubernetes)${NC}"
fi
}
# Install RuvBot
install_ruvbot() {
step "Installing RuvBot"
PACKAGE="ruvbot"
if [ "$RUVBOT_VERSION" != "latest" ]; then
PACKAGE="ruvbot@$RUVBOT_VERSION"
info "Installing version $RUVBOT_VERSION"
fi
if [ "$RUVBOT_GLOBAL" = "true" ]; then
npm install -g "$PACKAGE" 2>/dev/null || sudo npm install -g "$PACKAGE"
success "RuvBot installed globally"
else
npm install "$PACKAGE"
success "RuvBot installed locally"
fi
# Verify installation
if command -v ruvbot &> /dev/null; then
INSTALLED_VERSION=$(ruvbot --version 2>/dev/null || echo "unknown")
success "RuvBot $INSTALLED_VERSION is ready"
else
success "RuvBot installed (use 'npx ruvbot' to run)"
fi
}
# Install optional dependencies for channels
install_channel_deps() {
local channel=$1
step "Installing $channel dependencies"
case "$channel" in
slack)
npm install @slack/bolt @slack/web-api 2>/dev/null
success "Slack SDK installed (@slack/bolt, @slack/web-api)"
;;
discord)
npm install discord.js 2>/dev/null
success "Discord.js installed"
;;
telegram)
npm install telegraf 2>/dev/null
success "Telegraf installed"
;;
all)
npm install @slack/bolt @slack/web-api discord.js telegraf 2>/dev/null
success "All channel dependencies installed"
;;
esac
}
# Initialize project
init_project() {
step "Initializing RuvBot project"
if [ "$RUVBOT_GLOBAL" = "true" ]; then
ruvbot init --yes
else
npx ruvbot init --yes
fi
success "Project initialized"
}
# Configure channel interactively
configure_channel() {
local channel=$1
step "Configuring $channel"
case "$channel" in
slack)
echo ""
echo " To set up Slack, you'll need credentials from:"
echo -e " ${CYAN}https://api.slack.com/apps${NC}"
echo ""
read -p " SLACK_BOT_TOKEN (xoxb-...): " SLACK_BOT_TOKEN
read -p " SLACK_SIGNING_SECRET: " SLACK_SIGNING_SECRET
read -p " SLACK_APP_TOKEN (xapp-...): " SLACK_APP_TOKEN
{
echo "SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN"
echo "SLACK_SIGNING_SECRET=$SLACK_SIGNING_SECRET"
echo "SLACK_APP_TOKEN=$SLACK_APP_TOKEN"
} >> .env
success "Slack configuration saved to .env"
;;
discord)
echo ""
echo " To set up Discord, you'll need credentials from:"
echo -e " ${CYAN}https://discord.com/developers/applications${NC}"
echo ""
read -p " DISCORD_TOKEN: " DISCORD_TOKEN
read -p " DISCORD_CLIENT_ID: " DISCORD_CLIENT_ID
read -p " DISCORD_GUILD_ID (optional): " DISCORD_GUILD_ID
{
echo "DISCORD_TOKEN=$DISCORD_TOKEN"
echo "DISCORD_CLIENT_ID=$DISCORD_CLIENT_ID"
[ -n "$DISCORD_GUILD_ID" ] && echo "DISCORD_GUILD_ID=$DISCORD_GUILD_ID"
} >> .env
success "Discord configuration saved to .env"
;;
telegram)
echo ""
echo " To set up Telegram, get a token from:"
echo -e " ${CYAN}@BotFather${NC} on Telegram"
echo ""
read -p " TELEGRAM_BOT_TOKEN: " TELEGRAM_BOT_TOKEN
echo "TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN" >> .env
success "Telegram configuration saved to .env"
;;
esac
}
# Deploy to Cloud Run
deploy_cloudrun() {
step "Deploying to Google Cloud Run"
if [ "$GCLOUD_AVAILABLE" != "true" ]; then
error "gcloud CLI is required. Install from https://cloud.google.com/sdk"
fi
# Check authentication
if ! gcloud auth list --filter=status:ACTIVE --format="value(account)" 2>/dev/null | head -1; then
warn "Not authenticated with gcloud"
info "Running 'gcloud auth login'..."
gcloud auth login
fi
# Get project
CURRENT_PROJECT=$(gcloud config get-value project 2>/dev/null || echo "")
echo ""
read -p " GCP Project ID [$CURRENT_PROJECT]: " PROJECT_ID
PROJECT_ID="${PROJECT_ID:-$CURRENT_PROJECT}"
if [ -z "$PROJECT_ID" ]; then
error "Project ID is required"
fi
gcloud config set project "$PROJECT_ID" 2>/dev/null
# Get region
read -p " Region [us-central1]: " REGION
REGION="${REGION:-us-central1}"
# Get service name
read -p " Service name [ruvbot]: " SERVICE_NAME
SERVICE_NAME="${SERVICE_NAME:-ruvbot}"
# Get API key
echo ""
echo " LLM Provider:"
echo " 1. OpenRouter (recommended - Gemini, Claude, GPT)"
echo " 2. Anthropic (Claude only)"
read -p " Choose [1]: " PROVIDER_CHOICE
PROVIDER_CHOICE="${PROVIDER_CHOICE:-1}"
if [ "$PROVIDER_CHOICE" = "1" ]; then
read -p " OPENROUTER_API_KEY: " API_KEY
ENV_VARS="OPENROUTER_API_KEY=$API_KEY,DEFAULT_MODEL=google/gemini-2.0-flash-001"
else
read -p " ANTHROPIC_API_KEY: " API_KEY
ENV_VARS="ANTHROPIC_API_KEY=$API_KEY"
fi
# Channel configuration
echo ""
read -p " Configure Slack? [y/N]: " SETUP_SLACK
if [[ "$SETUP_SLACK" =~ ^[Yy]$ ]]; then
read -p " SLACK_BOT_TOKEN: " SLACK_BOT_TOKEN
read -p " SLACK_SIGNING_SECRET: " SLACK_SIGNING_SECRET
ENV_VARS="$ENV_VARS,SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN,SLACK_SIGNING_SECRET=$SLACK_SIGNING_SECRET"
fi
read -p " Configure Telegram? [y/N]: " SETUP_TELEGRAM
if [[ "$SETUP_TELEGRAM" =~ ^[Yy]$ ]]; then
read -p " TELEGRAM_BOT_TOKEN: " TELEGRAM_BOT_TOKEN
ENV_VARS="$ENV_VARS,TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN"
fi
# Enable required APIs
info "Enabling required GCP APIs..."
gcloud services enable run.googleapis.com containerregistry.googleapis.com cloudbuild.googleapis.com 2>/dev/null
# Create Dockerfile if it doesn't exist
if [ ! -f "Dockerfile" ]; then
info "Creating Dockerfile..."
cat > Dockerfile << 'DOCKERFILE'
FROM node:20-slim
WORKDIR /app
# Install curl for health checks
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Install ruvbot
RUN npm install -g ruvbot
# Create directories
RUN mkdir -p /app/data /app/plugins /app/skills
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:${PORT:-8080}/health || exit 1
# Start command
CMD ["ruvbot", "start", "--port", "8080"]
DOCKERFILE
success "Dockerfile created"
fi
# Deploy
info "Deploying to Cloud Run (this may take a few minutes)..."
gcloud run deploy "$SERVICE_NAME" \
--source . \
--platform managed \
--region "$REGION" \
--allow-unauthenticated \
--port 8080 \
--memory 512Mi \
--min-instances 0 \
--max-instances 10 \
--set-env-vars="$ENV_VARS" \
--quiet
# Get URL
SERVICE_URL=$(gcloud run services describe "$SERVICE_NAME" --region "$REGION" --format='value(status.url)')
echo ""
echo -e "${GREEN}═══════════════════════════════════════${NC}"
echo -e "${BOLD}🚀 RuvBot deployed successfully!${NC}"
echo -e "${GREEN}═══════════════════════════════════════${NC}"
echo ""
echo -e " URL: ${CYAN}$SERVICE_URL${NC}"
echo -e " Health: ${CYAN}$SERVICE_URL/health${NC}"
echo -e " API: ${CYAN}$SERVICE_URL/api/status${NC}"
echo -e " Models: ${CYAN}$SERVICE_URL/api/models${NC}"
echo ""
echo " Quick test:"
echo -e " ${DIM}curl $SERVICE_URL/health${NC}"
echo ""
# Set Telegram webhook if configured
if [ -n "$TELEGRAM_BOT_TOKEN" ]; then
WEBHOOK_URL="$SERVICE_URL/telegram/webhook"
info "Setting Telegram webhook..."
curl -s "https://api.telegram.org/bot$TELEGRAM_BOT_TOKEN/setWebhook?url=$WEBHOOK_URL" > /dev/null
success "Telegram webhook: $WEBHOOK_URL"
fi
}
# Deploy to Docker
deploy_docker() {
step "Deploying with Docker"
if [ "$DOCKER_AVAILABLE" != "true" ]; then
error "Docker is required. Install from https://docker.com"
fi
# Get configuration
read -p " Container name [ruvbot]: " CONTAINER_NAME
CONTAINER_NAME="${CONTAINER_NAME:-ruvbot}"
read -p " Port [3000]: " PORT
PORT="${PORT:-3000}"
# Create docker-compose.yml
info "Creating docker-compose.yml..."
cat > docker-compose.yml << COMPOSE
version: '3.8'
services:
ruvbot:
image: node:20-slim
container_name: $CONTAINER_NAME
working_dir: /app
command: sh -c "npm install -g ruvbot && ruvbot start --port 3000"
ports:
- "$PORT:3000"
environment:
- OPENROUTER_API_KEY=\${OPENROUTER_API_KEY}
- ANTHROPIC_API_KEY=\${ANTHROPIC_API_KEY}
- SLACK_BOT_TOKEN=\${SLACK_BOT_TOKEN}
- SLACK_SIGNING_SECRET=\${SLACK_SIGNING_SECRET}
- SLACK_APP_TOKEN=\${SLACK_APP_TOKEN}
- DISCORD_TOKEN=\${DISCORD_TOKEN}
- DISCORD_CLIENT_ID=\${DISCORD_CLIENT_ID}
- TELEGRAM_BOT_TOKEN=\${TELEGRAM_BOT_TOKEN}
volumes:
- ./data:/app/data
- ./plugins:/app/plugins
- ./skills:/app/skills
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
restart: unless-stopped
COMPOSE
success "docker-compose.yml created"
# Start containers
read -p " Start containers now? [Y/n]: " START_NOW
START_NOW="${START_NOW:-Y}"
if [[ "$START_NOW" =~ ^[Yy]$ ]]; then
info "Starting Docker containers..."
docker-compose up -d
echo ""
echo -e "${GREEN}═══════════════════════════════════════${NC}"
echo -e "${BOLD}🚀 RuvBot is running!${NC}"
echo -e "${GREEN}═══════════════════════════════════════${NC}"
echo ""
echo -e " URL: ${CYAN}http://localhost:$PORT${NC}"
echo -e " Health: ${CYAN}http://localhost:$PORT/health${NC}"
echo -e " Logs: ${DIM}docker-compose logs -f${NC}"
echo -e " Stop: ${DIM}docker-compose down${NC}"
echo ""
fi
}
# Deploy to Kubernetes
deploy_k8s() {
step "Deploying to Kubernetes"
if [ "$KUBECTL_AVAILABLE" != "true" ]; then
error "kubectl is required. Install from https://kubernetes.io/docs/tasks/tools/"
fi
# Get namespace
read -p " Namespace [default]: " NAMESPACE
NAMESPACE="${NAMESPACE:-default}"
# Get API key
read -p " OPENROUTER_API_KEY: " API_KEY
info "Creating Kubernetes manifests..."
mkdir -p k8s
# Create secret
cat > k8s/secret.yaml << SECRET
apiVersion: v1
kind: Secret
metadata:
name: ruvbot-secrets
namespace: $NAMESPACE
type: Opaque
stringData:
OPENROUTER_API_KEY: "$API_KEY"
DEFAULT_MODEL: "google/gemini-2.0-flash-001"
SECRET
# Create deployment
cat > k8s/deployment.yaml << DEPLOYMENT
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruvbot
namespace: $NAMESPACE
spec:
replicas: 2
selector:
matchLabels:
app: ruvbot
template:
metadata:
labels:
app: ruvbot
spec:
containers:
- name: ruvbot
image: node:20-slim
command: ["sh", "-c", "npm install -g ruvbot && ruvbot start --port 3000"]
ports:
- containerPort: 3000
envFrom:
- secretRef:
name: ruvbot-secrets
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 60
periodSeconds: 30
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
---
apiVersion: v1
kind: Service
metadata:
name: ruvbot
namespace: $NAMESPACE
spec:
selector:
app: ruvbot
ports:
- port: 80
targetPort: 3000
type: LoadBalancer
DEPLOYMENT
success "Kubernetes manifests created in k8s/"
read -p " Apply manifests now? [Y/n]: " APPLY_NOW
APPLY_NOW="${APPLY_NOW:-Y}"
if [[ "$APPLY_NOW" =~ ^[Yy]$ ]]; then
kubectl apply -f k8s/
echo ""
success "Kubernetes resources created"
echo ""
echo " Check status:"
echo -e " ${DIM}kubectl get pods -l app=ruvbot${NC}"
echo ""
echo " Get service URL:"
echo -e " ${DIM}kubectl get svc ruvbot${NC}"
echo ""
fi
}
# Deployment wizard
deployment_wizard() {
step "Deployment Options"
echo ""
echo " 1. Local (development)"
echo " 2. Docker"
echo " 3. Google Cloud Run"
echo " 4. Kubernetes"
echo " 5. Skip deployment"
echo ""
read -p " Select [5]: " DEPLOY_CHOICE
DEPLOY_CHOICE="${DEPLOY_CHOICE:-5}"
case "$DEPLOY_CHOICE" in
1)
info "Starting local development server..."
if [ "$RUVBOT_GLOBAL" = "true" ]; then
ruvbot start --debug
else
npx ruvbot start --debug
fi
;;
2) deploy_docker ;;
3) deploy_cloudrun ;;
4) deploy_k8s ;;
5) info "Skipping deployment" ;;
*) warn "Invalid option, skipping deployment" ;;
esac
}
# Interactive setup wizard
run_wizard() {
step "RuvBot Setup Wizard"
# Ensure .env exists
touch .env 2>/dev/null || true
# LLM Provider
echo ""
echo " ${BOLD}Step 1: LLM Provider${NC}"
echo " ───────────────────"
echo " 1. OpenRouter (Gemini 2.5, Claude, GPT - recommended)"
echo " 2. Anthropic (Claude only)"
echo " 3. Skip (configure later)"
read -p " Select [1]: " PROVIDER
PROVIDER="${PROVIDER:-1}"
case "$PROVIDER" in
1)
read -p " OPENROUTER_API_KEY: " OPENROUTER_KEY
{
echo "OPENROUTER_API_KEY=$OPENROUTER_KEY"
echo "DEFAULT_MODEL=google/gemini-2.0-flash-001"
} >> .env
success "OpenRouter configured"
;;
2)
read -p " ANTHROPIC_API_KEY: " ANTHROPIC_KEY
echo "ANTHROPIC_API_KEY=$ANTHROPIC_KEY" >> .env
success "Anthropic configured"
;;
3) info "Skipping LLM configuration" ;;
esac
# Channel Configuration
echo ""
echo " ${BOLD}Step 2: Channel Integrations${NC}"
echo " ────────────────────────────"
echo " 1. Slack"
echo " 2. Discord"
echo " 3. Telegram"
echo " 4. All channels"
echo " 5. Skip (configure later)"
read -p " Select [5]: " CHANNELS
CHANNELS="${CHANNELS:-5}"
case "$CHANNELS" in
1)
install_channel_deps "slack"
configure_channel "slack"
;;
2)
install_channel_deps "discord"
configure_channel "discord"
;;
3)
install_channel_deps "telegram"
configure_channel "telegram"
;;
4)
install_channel_deps "all"
configure_channel "slack"
configure_channel "discord"
configure_channel "telegram"
;;
5) info "Skipping channel configuration" ;;
esac
# Deployment
echo ""
echo " ${BOLD}Step 3: Deployment${NC}"
echo " ──────────────────"
deployment_wizard
}
# Print next steps
print_next_steps() {
echo ""
echo -e "${BOLD}📚 Quick Start${NC}"
echo "═══════════════════════════════════════"
echo ""
echo " Configure LLM provider:"
echo -e " ${CYAN}export OPENROUTER_API_KEY=sk-or-...${NC}"
echo ""
echo " Run diagnostics:"
echo -e " ${CYAN}ruvbot doctor${NC}"
echo ""
echo " Start the bot:"
echo -e " ${CYAN}ruvbot start${NC}"
echo ""
echo " Channel setup guides:"
echo -e " ${CYAN}ruvbot channels setup slack${NC}"
echo -e " ${CYAN}ruvbot channels setup discord${NC}"
echo -e " ${CYAN}ruvbot channels setup telegram${NC}"
echo ""
echo " Deploy templates:"
echo -e " ${CYAN}ruvbot templates list${NC}"
echo -e " ${CYAN}ruvbot deploy code-reviewer${NC}"
echo ""
echo " Deploy to Cloud Run:"
echo -e " ${CYAN}ruvbot deploy cloudrun${NC}"
echo ""
echo -e "${DIM}Docs: https://github.com/ruvnet/ruvector/tree/main/npm/packages/ruvbot${NC}"
echo ""
}
# Main
main() {
print_banner
check_dependencies
install_ruvbot
# Handle channel installation
if [ -n "$RUVBOT_CHANNEL" ]; then
install_channel_deps "$RUVBOT_CHANNEL"
fi
# Handle initialization
if [ "$RUVBOT_INIT" = "true" ]; then
init_project
fi
# Handle wizard
if [ "$RUVBOT_WIZARD" = "true" ]; then
run_wizard
elif [ -n "$RUVBOT_DEPLOY" ]; then
# Handle deployment without wizard
case "$RUVBOT_DEPLOY" in
cloudrun|cloud-run|gcp) deploy_cloudrun ;;
docker) deploy_docker ;;
k8s|kubernetes) deploy_k8s ;;
*) warn "Unknown deployment target: $RUVBOT_DEPLOY" ;;
esac
fi
print_next_steps
}
main "$@"