Files
light-heart-labs--dreamserver/ods/scripts/first-boot-demo.sh
T
wehub-resource-sync 9e8f1bbeed
Dashboard / frontend (push) Failing after 0s
Dashboard / api (push) Failing after 0s
Lint PowerShell / powershell-lint (ubuntu-latest) (push) Failing after 1s
Python Lint / Lint Python with Ruff (push) Failing after 1s
ShellCheck / Lint shell scripts (push) Failing after 1s
Matrix Smoke / linux-smoke (push) Failing after 1s
Matrix Smoke / distro: cachyos (push) Failing after 15s
Matrix Smoke / distro: linux-mint-21.3 (push) Failing after 15s
Matrix Smoke / distro: debian-12 (push) Failing after 5m21s
Matrix Smoke / distro: fedora-41 (push) Failing after 4m56s
Matrix Smoke / distro: ubuntu-24.04 (push) Failing after 2m13s
Matrix Smoke / distro: rocky-9 (push) Failing after 10m39s
Matrix Smoke / distro: manjaro (push) Failing after 12m11s
Matrix Smoke / distro: opensuse-tw (push) Failing after 11m53s
Matrix Smoke / distro: archlinux (push) Failing after 20m3s
Matrix Smoke / distro: ubuntu-22.04 (push) Failing after 13m49s
Validate .env Schema / tier-1-env-validation (push) Successful in 52s
Validate .env Schema / tier-2-env-validation (push) Successful in 44s
Validate .env Schema / tier-3-env-validation (push) Successful in 52s
Validate .env Schema / tier-4-env-validation (push) Successful in 51s
Validate Extensions Catalog / Check catalog is up-to-date (push) Failing after 9m47s
Secret Scan / Scan for secrets (push) Failing after 21m4s
Validate Docker Compose / Validate Docker Compose files (push) Has been cancelled
Python Type Check / Type check with mypy (push) Has been cancelled
Validate .env Schema / tier-0-env-validation (push) Has been cancelled
Test Linux / integration-smoke (push) Has been cancelled
Lint PowerShell / powershell-lint (windows-latest) (push) Has been cancelled
Matrix Smoke / macos-smoke (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:31:33 +08:00

303 lines
9.3 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
# ODS First Boot Demo
# Shows off what your local AI stack can do in under 2 minutes
#
# Usage: ./first-boot-demo.sh [--all] [--quick]
# Mission: M5 (Clonable ODS Setup Server)
set -euo pipefail
#=============================================================================
# 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'
BOLD='\033[1m'
#=============================================================================
# Config — resolve from service registry when available
#=============================================================================
_DEMO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
if [[ -f "$_DEMO_DIR/lib/service-registry.sh" ]]; then
export SCRIPT_DIR="$_DEMO_DIR"
. "$_DEMO_DIR/lib/service-registry.sh"
sr_load
[[ -f "$_DEMO_DIR/lib/safe-env.sh" ]] && . "$_DEMO_DIR/lib/safe-env.sh"
load_env_file "$_DEMO_DIR/.env"
sr_resolve_ports
fi
LLM_URL="${LLM_URL:-http://localhost:${SERVICE_PORTS[llama-server]:-11434}}"
WHISPER_URL="${WHISPER_URL:-http://localhost:${SERVICE_PORTS[whisper]:-9000}}"
PIPER_URL="${PIPER_URL:-http://localhost:${SERVICE_PORTS[tts]:-8880}}"
N8N_URL="${N8N_URL:-http://localhost:${SERVICE_PORTS[n8n]:-5678}}"
WEBUI_URL="${WEBUI_URL:-http://localhost:${SERVICE_PORTS[open-webui]:-3000}}"
QUICK_MODE=false
ALL_MODE=false
while [[ $# -gt 0 ]]; do
case $1 in
--quick) QUICK_MODE=true; shift ;;
--all) ALL_MODE=true; shift ;;
-h|--help)
echo "Usage: $0 [--quick] [--all]"
echo " --quick Skip slow demos, just show what's available"
echo " --all Run all demos including voice (requires audio files)"
exit 0
;;
*) shift ;;
esac
done
#=============================================================================
# Helpers
#=============================================================================
header() {
echo ""
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BOLD}${CYAN} $1${NC}"
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}
demo() {
echo -e "\n${MAGENTA}${NC} ${BOLD}$1${NC}"
}
success() {
echo -e "${GREEN}${NC} $1"
}
fail() {
echo -e "${RED}${NC} $1"
}
info() {
echo -e "${CYAN}${NC} $1"
}
wait_key() {
if [[ "$QUICK_MODE" != "true" ]]; then
echo -e "\n${YELLOW}Press Enter to continue...${NC}"
read -r
fi
}
check_service() {
local name=$1
local url=$2
local endpoint=${3:-/health}
if curl -sf "${url}${endpoint}" > /dev/null 2>&1; then
success "$name is running at $url"
return 0
else
fail "$name not responding at $url"
return 1
fi
}
#=============================================================================
# Welcome
#=============================================================================
clear
echo ""
echo -e "${BOLD}${CYAN}"
cat << 'EOF'
OOOOO DDDD SSSSS
OO OO DD DD SS
OO OO DD DD SSS
OO OO DD DD SS
OOOOO DDDD SSSS
EOF
echo -e "${NC}"
echo -e "${BOLD}ODS - First Boot Demo${NC}"
echo -e "Everything runs on YOUR hardware. No cloud. No API costs. Full privacy.\n"
#=============================================================================
# Health Check
#=============================================================================
header "🔍 Checking Services"
SERVICES_OK=0
SERVICES_TOTAL=0
# Core services
((SERVICES_TOTAL++)) || true
if check_service "LLM (llama-server)" "$LLM_URL" "/health"; then
((SERVICES_OK++)) || true
LLM_AVAILABLE=true
else
LLM_AVAILABLE=false
fi
((SERVICES_TOTAL++)) || true
if check_service "Open WebUI" "$WEBUI_URL" "/"; then
((SERVICES_OK++)) || true
fi
# Optional services
if curl -sf "${WHISPER_URL}/health" > /dev/null 2>&1; then
success "Whisper STT is running (voice input enabled)"
WHISPER_AVAILABLE=true
((SERVICES_OK++)) || true
((SERVICES_TOTAL++)) || true
else
info "Whisper STT not running (voice input disabled)"
WHISPER_AVAILABLE=false
fi
if curl -sf "${PIPER_URL}" > /dev/null 2>&1; then
success "OpenTTS TTS is running (voice output enabled)"
PIPER_AVAILABLE=true
((SERVICES_OK++)) || true
((SERVICES_TOTAL++)) || true
else
info "OpenTTS TTS not running (voice output disabled)"
PIPER_AVAILABLE=false
fi
if curl -sf "${N8N_URL}/healthz" > /dev/null 2>&1; then
success "n8n Workflows is running (automation enabled)"
N8N_AVAILABLE=true
((SERVICES_OK++)) || true
((SERVICES_TOTAL++)) || true
else
info "n8n not running (automation disabled)"
N8N_AVAILABLE=false
fi
echo ""
echo -e "${BOLD}Services: ${SERVICES_OK}/${SERVICES_TOTAL} running${NC}"
if [[ "$LLM_AVAILABLE" != "true" ]]; then
echo -e "\n${RED}LLM (llama-server) is required for demos. Is it still loading?${NC}"
echo "Check status: docker compose logs -f llama-server"
exit 1
fi
wait_key
#=============================================================================
# Demo 1: Chat Completion
#=============================================================================
header "💬 Demo 1: Local Chat Completion"
demo "Asking your local AI a question..."
RESPONSE=$(curl -sf "${LLM_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-32B-Instruct-AWQ",
"messages": [{"role": "user", "content": "In one sentence, what makes local AI special?"}],
"max_tokens": 100,
"temperature": 0.7
}' 2>/dev/null | jq -r '.choices[0].message.content' 2>/dev/null || echo "")
if [[ -n "$RESPONSE" && "$RESPONSE" != "null" ]]; then
echo ""
echo -e "${GREEN}Response:${NC}"
echo -e " ${RESPONSE}"
echo ""
success "Local LLM responded! No API calls, no cloud, just your GPU."
else
fail "No response from LLM"
fi
wait_key
#=============================================================================
# Demo 2: Code Assistance
#=============================================================================
header "🧑‍💻 Demo 2: Code Assistance"
demo "Asking for help with a Python function..."
CODE_RESPONSE=$(curl -sf "${LLM_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-32B-Instruct-AWQ",
"messages": [{"role": "user", "content": "Write a Python one-liner to reverse a string. Just the code, no explanation."}],
"max_tokens": 50,
"temperature": 0.3
}' 2>/dev/null | jq -r '.choices[0].message.content' 2>/dev/null || echo "")
if [[ -n "$CODE_RESPONSE" && "$CODE_RESPONSE" != "null" ]]; then
echo ""
echo -e "${GREEN}Generated code:${NC}"
echo -e " ${CODE_RESPONSE}"
echo ""
success "Code assistant works! Great for development."
else
fail "No response from code assistant"
fi
wait_key
#=============================================================================
# Demo 3: Streaming
#=============================================================================
header "📡 Demo 3: Streaming Response"
demo "Watching tokens stream in real-time..."
echo ""
# Simple streaming demo - just show it works
curl -sN "${LLM_URL}/v1/chat/completions" \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-32B-Instruct-AWQ",
"messages": [{"role": "user", "content": "Count from 1 to 5, one number per line."}],
"max_tokens": 50,
"temperature": 0,
"stream": true
}' 2>/dev/null | while read -r line; do
if [[ "$line" == data:* ]]; then
content=$(echo "${line#data: }" | jq -r '.choices[0].delta.content // empty' 2>/dev/null)
if [[ -n "$content" ]]; then
printf "%s" "$content"
fi
fi
done
echo ""
echo ""
success "Streaming works! Great for real-time UIs."
wait_key
#=============================================================================
# Summary
#=============================================================================
header "🎉 Demo Complete!"
echo ""
echo -e "${BOLD}What you just saw:${NC}"
echo " ✓ Local LLM responding to prompts"
echo " ✓ Code assistance capabilities"
echo " ✓ Real-time streaming"
echo ""
echo -e "${BOLD}What's available:${NC}"
echo " • Open WebUI: ${WEBUI_URL}"
[[ "$N8N_AVAILABLE" == "true" ]] && echo " • n8n Workflows: ${N8N_URL}"
[[ "$WHISPER_AVAILABLE" == "true" ]] && echo " • Whisper STT: ${WHISPER_URL}"
[[ "$PIPER_AVAILABLE" == "true" ]] && echo " • OpenTTS TTS: ${PIPER_URL}"
echo ""
echo -e "${BOLD}Next steps:${NC}"
echo " 1. Open ${WEBUI_URL} and start chatting"
echo " 2. Import workflows from ./workflows/ into n8n"
echo " 3. Try the voice demo: ./scripts/voice-demo.sh"
echo " 4. OpenClaw agent: http://localhost:7860"
echo ""
echo -e "${CYAN}Everything runs locally. Your data stays private. Enjoy! 🚀${NC}"
echo ""