#!/bin/bash # start-openclaw.sh -- HF Spaces full startup (13 phases + post-gateway) set -e export OPENCLAW_STATE_DIR="${OPENCLAW_STATE_DIR:-/root/.openclaw}" export PORT="${PORT:-7860}" export OPENCLAW_GATEWAY_PORT="${OPENCLAW_GATEWAY_PORT:-18889}" echo "================================================" echo " OpenClaw AI Gateway -- HF Spaces Startup" echo "================================================" # --- Phase 1: directories --- echo "[1/13] Creating directories..." mkdir -p "${OPENCLAW_STATE_DIR}"/{agents/main/sessions,credentials,sessions,workspace,extensions} # --- Phase 2: System tools pre-installed (OpenClaw, Caddy, WeChat CLI if enabled) --- echo "[2/13] System tools pre-installed (OpenClaw, Caddy, Claude Code)" # --- Phase 3: restore backup --- echo "[3/13] Restoring from backup..." python3 /app/backup-manager.py restore # --- Phase 4: generate config --- echo "[4/13] Generating OpenClaw config..." python3 /app/config-generator.py # --- Phase 5-8: postpone agents/skills (will run after gateway warmup) --- echo "[5-8/13] Skip -- post-gateway tasks postponed" # --- Phase 9: backup scheduler --- echo "[9/13] Starting backup scheduler..." python3 /app/backup-manager.py scheduler & BACKUP_PID=$! echo " -> Backup scheduler PID: $BACKUP_PID" # --- Phase 10: cc-switch-web --- echo "[10/13] Starting cc-switch-web..." CCSWITCH_BIN="${OPENCLAW_STATE_DIR}/cc-switch-server" if [[ ! -f "$CCSWITCH_BIN" ]]; then curl -fsSL "https://github.com/Laliet/cc-switch-web/releases/download/v0.11.1/cc-switch-server-linux-x86_64" \ -o "$CCSWITCH_BIN" 2>/dev/null && chmod +x "$CCSWITCH_BIN" || echo " WARNING: Download failed" fi if [[ -f "$CCSWITCH_BIN" ]]; then HOST=0.0.0.0 PORT=3000 "$CCSWITCH_BIN" > /dev/null 2>&1 & CCSWITCH_PID=$! echo " -> cc-switch-web started (PID $CCSWITCH_PID)" else echo " -> cc-switch-web not available" fi # --- Phase 11: Caddy reverse proxy --- echo "[11/13] Starting Caddy reverse proxy..." caddy run --config /app/Caddyfile > /dev/null 2>&1 & CADDY_PID=$! echo " -> Caddy PID: $CADDY_PID" trap "kill $CADDY_PID 2>/dev/null" EXIT # --- Phase 12: Third-party integrations (WeChat, Feishu) --- echo "[12/13] Configuring third-party integrations (if enabled)..." if [[ "${WEIXIN_ENABLED:-false}" == "true" ]]; then echo " -> WeChat integration enabled, activating..." bash /app/scripts/wechat-activate.sh else echo " -> WeChat integration disabled (WEIXIN_ENABLED=false)" fi if [[ "${FEISHU_ENABLED:-false}" == "true" ]]; then echo " -> Feishu integration enabled, setting up..." bash /app/scripts/feishu-setup.sh else echo " -> Feishu integration disabled (FEISHU_ENABLED=false)" fi # --- Phase 13: Start OpenClaw Gateway --- echo "[13/13] Starting OpenClaw Gateway..." GATEWAY_LOG="${OPENCLAW_STATE_DIR}/gateway.log" openclaw gateway run --port "${OPENCLAW_GATEWAY_PORT}" > "$GATEWAY_LOG" 2>&1 & OPENCLAW_PID=$! echo " -> OpenClaw PID: $OPENCLAW_PID (on :${OPENCLAW_GATEWAY_PORT})" echo " -> Gateway log: $GATEWAY_LOG" # Stream gateway logs to stdout for debugging tail -f "$GATEWAY_LOG" 2>/dev/null & # Wait for gateway to be ready (via Caddy on $PORT) echo " -> Waiting for gateway to be ready (up to 90s) via Caddy on :$PORT..." for i in $(seq 1 30); do if curl -s -f --connect-timeout 3 --max-time 5 "http://localhost:${PORT}/health" >/dev/null 2>&1; then echo " -> Gateway ready!" break fi if [ $i -eq 10 ] || [ $i -eq 20 ]; then echo " -> Still waiting... (${i}x3s elapsed)" if ! kill -0 $OPENCLAW_PID 2>/dev/null; then echo " -> WARNING: Gateway process died! Last log lines:" tail -5 "$GATEWAY_LOG" 2>/dev/null || echo " -> (no log file)" break fi fi sleep 3 done # Check if gateway is alive after wait if ! kill -0 $OPENCLAW_PID 2>/dev/null; then echo " -> ERROR: Gateway process exited. Full log:" cat "$GATEWAY_LOG" 2>/dev/null || echo " -> (no log)" exit 1 fi # Extra wait for provider auth pre-warming echo " -> Waiting for provider auth warmup (60s)..." for i in 1 2 3 4 5 6 7 8 9 10 11 12; do if curl -s -f --connect-timeout 3 --max-time 5 "http://localhost:${PORT}/health" >/dev/null 2>&1; then : # still healthy fi sleep 5 done echo " -> Warmup window done" # --- Post-gateway: create agents, configure skills --- ( sleep 2 echo "[5/13] Creating agents..." for i in 1 2 3 4 5; do agent_id="agent-${i}" if timeout 15 openclaw agents list 2>/dev/null | grep -q "\"${agent_id}\""; then echo " -> Agent ${agent_id} exists, skipping" else echo " -> Creating agent ${agent_id}..." openclaw agents add "${agent_id}" \ --workspace "${OPENCLAW_STATE_DIR}/workspace-agent-${i}" \ --non-interactive 2>/dev/null || true fi done echo "[6/13] Configuring skills..." allow_bundled="${SKILLS_ALLOW_BUNDLED:-multi-search-cn,github,summarize}" IFS=',' read -ra ALLOW <<< "$allow_bundled" for skill in "${ALLOW[@]}"; do [[ -n "$skill" ]] && timeout 15 openclaw config set "skills.allowBundled[+]" "$skill" 2>/dev/null || true done echo "[7/13] Post-gateway setup done" ) & # Wait for gateway to exit (keep container alive) wait $OPENCLAW_PID