From 74001c7c3ee58e2cc5d8b3371b7279aaac6b7981 Mon Sep 17 00:00:00 2001 From: Gemini AI Date: Sun, 28 Dec 2025 00:43:08 +0400 Subject: [PATCH] fix: robust installers for all platforms (Windows, Linux, macOS) Windows: - Multiple Node.js installation methods (winget, chocolatey, direct MSI) - Clear restart instructions when Node.js is newly installed - Fallback to user profile directory if current dir not writable - Comprehensive health checks and error reporting Linux: - Support for apt, dnf, yum, pacman, zypper, apk package managers - NodeSource repository for newer Node.js versions - nvm fallback installation method - Graceful error handling with detailed troubleshooting macOS: - Xcode Command Line Tools detection and installation - Homebrew auto-installation - Apple Silicon (arm64) support with correct PATH setup - Multiple Node.js fallbacks (brew, nvm, official pkg) All platforms: - Binary-Free Mode as default (no OpenCode binary required) - Beautiful terminal output with progress indicators - Detailed logging to install.log - Post-install health checks --- Install-Linux.sh | 525 ++++++++++++++++++++++++++------------------ Install-Mac.sh | 471 +++++++++++++++++++++++++-------------- Install-Windows.bat | 427 +++++++++++++++++++++-------------- 3 files changed, 881 insertions(+), 542 deletions(-) diff --git a/Install-Linux.sh b/Install-Linux.sh index b767e6d..7fde54b 100644 --- a/Install-Linux.sh +++ b/Install-Linux.sh @@ -1,114 +1,173 @@ #!/bin/bash # NomadArch Installer for Linux -# Version: 0.5.0 - Binary-Free Mode +# Version: 0.6.0 - Robust Edition -set -euo pipefail +# Exit on error, but handle gracefully +set -u +# Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' +CYAN='\033[0;36m' NC='\033[0m' +BOLD='\033[1m' +# Script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TARGET_DIR="$SCRIPT_DIR" BIN_DIR="$TARGET_DIR/bin" LOG_FILE="$TARGET_DIR/install.log" ERRORS=0 WARNINGS=0 -NEEDS_FALLBACK=0 -BINARY_FREE_MODE=0 +BINARY_FREE_MODE=1 +# Logging function log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" } -echo "" -echo "NomadArch Installer (Linux)" -echo "Version: 0.5.0 - Binary-Free Mode" -echo "" +print_header() { + echo "" + echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${CYAN}║${NC} ${BOLD}NomadArch Installer for Linux${NC} ${CYAN}║${NC}" + echo -e "${CYAN}║${NC} Version: 0.6.0 - Robust Edition ${CYAN}║${NC}" + echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" + echo "" +} -log "Installer started" +print_header +log "========== Installer started ==========" + +# ═══════════════════════════════════════════════════════════════ +# STEP 1: OS and Architecture Detection +# ═══════════════════════════════════════════════════════════════ +echo "[STEP 1/8] Detecting System..." -echo "[STEP 1/8] OS and Architecture Detection" OS_TYPE=$(uname -s) ARCH_TYPE=$(uname -m) -log "OS: $OS_TYPE" -log "Architecture: $ARCH_TYPE" +log "OS: $OS_TYPE, Arch: $ARCH_TYPE" if [[ "$OS_TYPE" != "Linux" ]]; then echo -e "${RED}[ERROR]${NC} This installer is for Linux. Current OS: $OS_TYPE" + echo " Use Install-Mac.sh for macOS or Install-Windows.bat for Windows." log "ERROR: Not Linux ($OS_TYPE)" exit 1 fi case "$ARCH_TYPE" in - x86_64) ARCH="x64" ;; + x86_64) ARCH="x64" ;; aarch64) ARCH="arm64" ;; - armv7l) ARCH="arm" ;; + armv7l) ARCH="arm" ;; *) - echo -e "${RED}[ERROR]${NC} Unsupported architecture: $ARCH_TYPE" - log "ERROR: Unsupported arch $ARCH_TYPE" - exit 1 + echo -e "${YELLOW}[WARN]${NC} Unusual architecture: $ARCH_TYPE (proceeding anyway)" + ARCH="$ARCH_TYPE" + ((WARNINGS++)) || true ;; esac echo -e "${GREEN}[OK]${NC} OS: Linux" -echo -e "${GREEN}[OK]${NC} Architecture: $ARCH_TYPE" +echo -e "${GREEN}[OK]${NC} Architecture: $ARCH_TYPE ($ARCH)" +# Detect distribution if [[ -f /etc/os-release ]]; then # shellcheck disable=SC1091 . /etc/os-release - echo -e "${GREEN}[INFO]${NC} Distribution: ${PRETTY_NAME:-unknown}" + DISTRO="${ID:-unknown}" + DISTRO_NAME="${PRETTY_NAME:-$DISTRO}" + echo -e "${GREEN}[INFO]${NC} Distribution: $DISTRO_NAME" +else + DISTRO="unknown" + DISTRO_NAME="Unknown Linux" fi +log "Distribution: $DISTRO_NAME" +# ═══════════════════════════════════════════════════════════════ +# STEP 2: Check Write Permissions +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 2/8] Checking write permissions" -mkdir -p "$BIN_DIR" +echo "[STEP 2/8] Checking Write Permissions..." + +mkdir -p "$BIN_DIR" 2>/dev/null || true + if ! touch "$SCRIPT_DIR/.install-write-test" 2>/dev/null; then echo -e "${YELLOW}[WARN]${NC} No write access to $SCRIPT_DIR" - TARGET_DIR="$HOME/.nomadarch-install" + TARGET_DIR="$HOME/.nomadarch" BIN_DIR="$TARGET_DIR/bin" LOG_FILE="$TARGET_DIR/install.log" mkdir -p "$BIN_DIR" if ! touch "$TARGET_DIR/.install-write-test" 2>/dev/null; then echo -e "${RED}[ERROR]${NC} Cannot write to $TARGET_DIR" - log "ERROR: Write permission denied to fallback" + log "ERROR: Write permission denied" exit 1 fi rm -f "$TARGET_DIR/.install-write-test" - NEEDS_FALLBACK=1 echo -e "${GREEN}[OK]${NC} Using fallback: $TARGET_DIR" else rm -f "$SCRIPT_DIR/.install-write-test" - echo -e "${GREEN}[OK]${NC} Write access OK" + echo -e "${GREEN}[OK]${NC} Write access verified" fi - log "Install target: $TARGET_DIR" +# ═══════════════════════════════════════════════════════════════ +# STEP 3: Detect Package Manager and sudo +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 3/8] Ensuring system dependencies" +echo "[STEP 3/8] Detecting Package Manager..." SUDO="" if [[ $EUID -ne 0 ]]; then if command -v sudo >/dev/null 2>&1; then SUDO="sudo" + echo -e "${GREEN}[OK]${NC} sudo available (may prompt for password)" else - echo -e "${RED}[ERROR]${NC} sudo is required to install dependencies" - log "ERROR: sudo not found" - exit 1 + echo -e "${YELLOW}[WARN]${NC} Not root and sudo not found. Package installation may fail." + ((WARNINGS++)) || true fi +else + echo -e "${GREEN}[OK]${NC} Running as root" fi +# Detect package manager +PACKAGE_MANAGER="" +if command -v apt-get >/dev/null 2>&1; then + PACKAGE_MANAGER="apt" + echo -e "${GREEN}[OK]${NC} Package manager: apt (Debian/Ubuntu)" +elif command -v dnf >/dev/null 2>&1; then + PACKAGE_MANAGER="dnf" + echo -e "${GREEN}[OK]${NC} Package manager: dnf (Fedora/RHEL)" +elif command -v yum >/dev/null 2>&1; then + PACKAGE_MANAGER="yum" + echo -e "${GREEN}[OK]${NC} Package manager: yum (CentOS/RHEL)" +elif command -v pacman >/dev/null 2>&1; then + PACKAGE_MANAGER="pacman" + echo -e "${GREEN}[OK]${NC} Package manager: pacman (Arch)" +elif command -v zypper >/dev/null 2>&1; then + PACKAGE_MANAGER="zypper" + echo -e "${GREEN}[OK]${NC} Package manager: zypper (openSUSE)" +elif command -v apk >/dev/null 2>&1; then + PACKAGE_MANAGER="apk" + echo -e "${GREEN}[OK]${NC} Package manager: apk (Alpine)" +else + echo -e "${YELLOW}[WARN]${NC} No recognized package manager found" + echo -e "${YELLOW}[INFO]${NC} You may need to install dependencies manually" + ((WARNINGS++)) || true +fi + +# Package installation helper install_packages() { - local manager="$1" - shift local packages=("$@") - echo -e "${BLUE}[INFO]${NC} Installing via $manager: ${packages[*]}" - case "$manager" in + if [[ -z "$PACKAGE_MANAGER" ]]; then + echo -e "${YELLOW}[WARN]${NC} Cannot install packages: no package manager" + return 1 + fi + + echo -e "${BLUE}[INFO]${NC} Installing: ${packages[*]}" + case "$PACKAGE_MANAGER" in apt) - $SUDO apt-get update -y + $SUDO apt-get update -y >/dev/null 2>&1 || true $SUDO apt-get install -y "${packages[@]}" ;; dnf) @@ -126,234 +185,276 @@ install_packages() { apk) $SUDO apk add --no-cache "${packages[@]}" ;; - *) - return 1 - ;; esac } -PACKAGE_MANAGER="" -if command -v apt-get >/dev/null 2>&1; then - PACKAGE_MANAGER="apt" -elif command -v dnf >/dev/null 2>&1; then - PACKAGE_MANAGER="dnf" -elif command -v yum >/dev/null 2>&1; then - PACKAGE_MANAGER="yum" -elif command -v pacman >/dev/null 2>&1; then - PACKAGE_MANAGER="pacman" -elif command -v zypper >/dev/null 2>&1; then - PACKAGE_MANAGER="zypper" -elif command -v apk >/dev/null 2>&1; then - PACKAGE_MANAGER="apk" -fi +# ═══════════════════════════════════════════════════════════════ +# STEP 4: Install Node.js +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 4/8] Checking Node.js..." -if [[ -z "$PACKAGE_MANAGER" ]]; then - echo -e "${RED}[ERROR]${NC} No supported package manager found." - echo "Install Node.js, npm, git, and curl manually." - log "ERROR: No package manager found" - exit 1 -fi +NODE_OK=0 +NPM_OK=0 -MISSING_PKGS=() -command -v curl >/dev/null 2>&1 || MISSING_PKGS+=("curl") -command -v git >/dev/null 2>&1 || MISSING_PKGS+=("git") - -if ! command -v node >/dev/null 2>&1; then - case "$PACKAGE_MANAGER" in - apt) MISSING_PKGS+=("nodejs" "npm") ;; - dnf|yum) MISSING_PKGS+=("nodejs" "npm") ;; - pacman) MISSING_PKGS+=("nodejs" "npm") ;; - zypper) MISSING_PKGS+=("nodejs18" "npm18") ;; - apk) MISSING_PKGS+=("nodejs" "npm") ;; - *) MISSING_PKGS+=("nodejs") ;; - esac -elif ! command -v npm >/dev/null 2>&1; then - MISSING_PKGS+=("npm") -fi - -if [[ ${#MISSING_PKGS[@]} -gt 0 ]]; then - install_packages "$PACKAGE_MANAGER" "${MISSING_PKGS[@]}" || { - echo -e "${YELLOW}[WARN]${NC} Some packages failed to install. Trying alternative method..." - if ! command -v node >/dev/null 2>&1; then - install_packages "$PACKAGE_MANAGER" "nodejs" || true +if command -v node >/dev/null 2>&1; then + NODE_VERSION=$(node --version 2>/dev/null || echo "unknown") + if [[ "$NODE_VERSION" != "unknown" ]]; then + NODE_MAJOR=$(echo "$NODE_VERSION" | sed 's/v//' | cut -d'.' -f1) + echo -e "${GREEN}[OK]${NC} Node.js: $NODE_VERSION" + NODE_OK=1 + + if [[ $NODE_MAJOR -lt 18 ]]; then + echo -e "${YELLOW}[WARN]${NC} Node.js 18+ recommended (current: $NODE_VERSION)" + ((WARNINGS++)) || true fi - } + fi fi -if ! command -v node >/dev/null 2>&1; then - echo -e "${RED}[ERROR]${NC} Node.js install failed." - log "ERROR: Node.js still missing" - exit 1 +if [[ $NODE_OK -eq 0 ]]; then + echo -e "${BLUE}[INFO]${NC} Node.js not found. Attempting installation..." + log "Node.js not found, installing" + + INSTALL_SUCCESS=0 + + # Try package manager first + if [[ -n "$PACKAGE_MANAGER" ]]; then + case "$PACKAGE_MANAGER" in + apt) + # Try NodeSource for newer versions + if curl -fsSL https://deb.nodesource.com/setup_20.x 2>/dev/null | $SUDO -E bash - >/dev/null 2>&1; then + $SUDO apt-get install -y nodejs && INSTALL_SUCCESS=1 + fi + # Fallback to distro package + if [[ $INSTALL_SUCCESS -eq 0 ]]; then + install_packages nodejs npm && INSTALL_SUCCESS=1 + fi + ;; + dnf|yum) + if curl -fsSL https://rpm.nodesource.com/setup_20.x 2>/dev/null | $SUDO bash - >/dev/null 2>&1; then + $SUDO "$PACKAGE_MANAGER" install -y nodejs && INSTALL_SUCCESS=1 + fi + if [[ $INSTALL_SUCCESS -eq 0 ]]; then + install_packages nodejs npm && INSTALL_SUCCESS=1 + fi + ;; + pacman) + install_packages nodejs npm && INSTALL_SUCCESS=1 + ;; + zypper) + install_packages nodejs18 npm18 && INSTALL_SUCCESS=1 + if [[ $INSTALL_SUCCESS -eq 0 ]]; then + install_packages nodejs npm && INSTALL_SUCCESS=1 + fi + ;; + apk) + install_packages nodejs npm && INSTALL_SUCCESS=1 + ;; + esac + fi + + # Try nvm as fallback + if [[ $INSTALL_SUCCESS -eq 0 ]] && command -v curl >/dev/null 2>&1; then + echo -e "${BLUE}[INFO]${NC} Trying nvm installation..." + export NVM_DIR="$HOME/.nvm" + if curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh 2>/dev/null | bash >/dev/null 2>&1; then + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + nvm install 20 && INSTALL_SUCCESS=1 + fi + fi + + if [[ $INSTALL_SUCCESS -eq 1 ]]; then + # Re-check + if command -v node >/dev/null 2>&1; then + NODE_VERSION=$(node --version) + echo -e "${GREEN}[OK]${NC} Node.js installed: $NODE_VERSION" + NODE_OK=1 + fi + fi + + if [[ $NODE_OK -eq 0 ]]; then + echo -e "${RED}[ERROR]${NC} Could not install Node.js automatically" + echo "" + echo "Please install Node.js manually:" + echo " Ubuntu/Debian: sudo apt install nodejs npm" + echo " Fedora: sudo dnf install nodejs npm" + echo " Arch: sudo pacman -S nodejs npm" + echo " Or visit: https://nodejs.org/" + echo "" + log "ERROR: Node.js installation failed" + ERRORS=$((ERRORS+1)) + + # Don't exit - let user see summary + fi fi -NODE_VERSION=$(node --version) -NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d'v' -f2 | cut -d'.' -f1) -echo -e "${GREEN}[OK]${NC} Node.js: $NODE_VERSION" -if [[ $NODE_MAJOR -lt 18 ]]; then - echo -e "${YELLOW}[WARN]${NC} Node.js 18+ is recommended" - ((WARNINGS++)) +# Check npm +if command -v npm >/dev/null 2>&1; then + NPM_VERSION=$(npm --version 2>/dev/null || echo "unknown") + if [[ "$NPM_VERSION" != "unknown" ]]; then + echo -e "${GREEN}[OK]${NC} npm: $NPM_VERSION" + NPM_OK=1 + fi fi -if ! command -v npm >/dev/null 2>&1; then - echo -e "${RED}[ERROR]${NC} npm is not available" - log "ERROR: npm missing after install" - exit 1 +if [[ $NPM_OK -eq 0 && $NODE_OK -eq 1 ]]; then + echo -e "${YELLOW}[WARN]${NC} npm not found, trying to install..." + install_packages npm || true + if command -v npm >/dev/null 2>&1; then + NPM_VERSION=$(npm --version) + echo -e "${GREEN}[OK]${NC} npm installed: $NPM_VERSION" + NPM_OK=1 + else + echo -e "${RED}[ERROR]${NC} npm not available" + ERRORS=$((ERRORS+1)) + fi fi -NPM_VERSION=$(npm --version) -echo -e "${GREEN}[OK]${NC} npm: $NPM_VERSION" + +# ═══════════════════════════════════════════════════════════════ +# STEP 5: Check Git and curl (optional) +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 5/8] Checking Optional Dependencies..." if command -v git >/dev/null 2>&1; then echo -e "${GREEN}[OK]${NC} Git: $(git --version)" else - echo -e "${YELLOW}[WARN]${NC} Git not found (optional)" - ((WARNINGS++)) + echo -e "${YELLOW}[INFO]${NC} Git not found (optional)" fi -echo "" -echo "[STEP 4/8] Installing npm dependencies" -cd "$SCRIPT_DIR" -log "Running npm install" -if ! npm install; then - echo -e "${RED}[ERROR]${NC} npm install failed" - log "ERROR: npm install failed" - exit 1 -fi - -echo -e "${GREEN}[OK]${NC} Dependencies installed" - -echo "" -echo "[STEP 5/8] OpenCode Binary (OPTIONAL - Binary-Free Mode Available)" -echo -e "${BLUE}[INFO]${NC} NomadArch now supports Binary-Free Mode!" -echo -e "${BLUE}[INFO]${NC} You can use the application without OpenCode binary." -echo -e "${BLUE}[INFO]${NC} Free models from OpenCode Zen are available without the binary." -mkdir -p "$BIN_DIR" - -echo "" -read -p "Skip OpenCode binary download? (Y for Binary-Free Mode / N to download) [Y]: " SKIP_CHOICE -SKIP_CHOICE="${SKIP_CHOICE:-Y}" - -if [[ "${SKIP_CHOICE^^}" == "Y" ]]; then - BINARY_FREE_MODE=1 - echo -e "${GREEN}[INFO]${NC} Skipping OpenCode binary - using Binary-Free Mode" - log "Using Binary-Free Mode" +if command -v curl >/dev/null 2>&1; then + echo -e "${GREEN}[OK]${NC} curl: available" else - OPENCODE_PINNED_VERSION="0.1.44" - OPENCODE_VERSION="$OPENCODE_PINNED_VERSION" + echo -e "${YELLOW}[INFO]${NC} curl not found (optional, installing...)" + install_packages curl || true +fi - LATEST_VERSION=$(curl -s --max-time 10 https://api.github.com/repos/sst/opencode/releases/latest 2>/dev/null | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//') - if [[ -n "$LATEST_VERSION" ]]; then - echo -e "${BLUE}[INFO]${NC} Latest available: v${LATEST_VERSION}, using pinned: v${OPENCODE_VERSION}" - fi +# ═══════════════════════════════════════════════════════════════ +# STEP 6: Install npm Dependencies +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 6/8] Installing Dependencies..." - OPENCODE_BASE="https://github.com/sst/opencode/releases/download/v${OPENCODE_VERSION}" - OPENCODE_URL="${OPENCODE_BASE}/opencode-linux-${ARCH}" - CHECKSUM_URL="${OPENCODE_BASE}/checksums.txt" - - NEEDS_DOWNLOAD=0 - if [[ -f "$BIN_DIR/opencode" ]]; then - EXISTING_VERSION=$("$BIN_DIR/opencode" --version 2>/dev/null | head -1 || echo "unknown") - if [[ "$EXISTING_VERSION" == *"$OPENCODE_VERSION"* ]] || [[ "$EXISTING_VERSION" != "unknown" ]]; then - echo -e "${GREEN}[OK]${NC} OpenCode binary exists (version: $EXISTING_VERSION)" - else - echo -e "${YELLOW}[WARN]${NC} Existing binary version mismatch, re-downloading..." - NEEDS_DOWNLOAD=1 - fi +if [[ $NODE_OK -eq 0 || $NPM_OK -eq 0 ]]; then + echo -e "${YELLOW}[SKIP]${NC} Skipping npm install (Node.js/npm not available)" +else + cd "$SCRIPT_DIR" + + if [[ ! -f "package.json" ]]; then + echo -e "${RED}[ERROR]${NC} package.json not found in $SCRIPT_DIR" + echo "Make sure you extracted the full NomadArch package." + log "ERROR: package.json missing" + ERRORS=$((ERRORS+1)) else - NEEDS_DOWNLOAD=1 - fi - - if [[ $NEEDS_DOWNLOAD -eq 1 ]]; then - echo -e "${BLUE}[INFO]${NC} Downloading OpenCode v${OPENCODE_VERSION} for ${ARCH}..." + echo -e "${BLUE}[INFO]${NC} Running npm install (this may take a few minutes)..." + log "Running npm install" - DOWNLOAD_SUCCESS=0 - for attempt in 1 2 3; do - if curl -L --fail --retry 3 -o "$BIN_DIR/opencode.tmp" "$OPENCODE_URL" 2>/dev/null; then - DOWNLOAD_SUCCESS=1 - break - fi - echo -e "${YELLOW}[WARN]${NC} Download attempt $attempt failed, retrying..." - sleep 2 - done - - if [[ $DOWNLOAD_SUCCESS -eq 0 ]]; then - echo -e "${YELLOW}[WARN]${NC} Failed to download OpenCode binary - using Binary-Free Mode" - BINARY_FREE_MODE=1 + if npm install --no-audit --no-fund 2>&1; then + echo -e "${GREEN}[OK]${NC} Dependencies installed" else - if curl -L --fail -o "$BIN_DIR/checksums.txt" "$CHECKSUM_URL" 2>/dev/null; then - EXPECTED_HASH=$(grep "opencode-linux-${ARCH}" "$BIN_DIR/checksums.txt" | awk '{print $1}') - ACTUAL_HASH=$(sha256sum "$BIN_DIR/opencode.tmp" | awk '{print $1}') - - if [[ "$ACTUAL_HASH" == "$EXPECTED_HASH" ]]; then - echo -e "${GREEN}[OK]${NC} Checksum verified" - else - echo -e "${YELLOW}[WARN]${NC} Checksum mismatch (may be OK for some versions)" - fi + echo -e "${YELLOW}[WARN]${NC} npm install had issues, trying with legacy peer deps..." + if npm install --legacy-peer-deps --no-audit --no-fund 2>&1; then + echo -e "${GREEN}[OK]${NC} Dependencies installed (with legacy peer deps)" + else + echo -e "${RED}[ERROR]${NC} npm install failed" + log "ERROR: npm install failed" + ERRORS=$((ERRORS+1)) fi - - mv "$BIN_DIR/opencode.tmp" "$BIN_DIR/opencode" - chmod +x "$BIN_DIR/opencode" - echo -e "${GREEN}[OK]${NC} OpenCode binary installed" fi fi fi +# ═══════════════════════════════════════════════════════════════ +# STEP 7: Build UI Assets +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 6/8] Building UI assets" -if [[ -d "$SCRIPT_DIR/packages/ui/dist" ]]; then +echo "[STEP 7/8] Building UI Assets..." + +if [[ $NODE_OK -eq 0 || $NPM_OK -eq 0 ]]; then + echo -e "${YELLOW}[SKIP]${NC} Skipping UI build (Node.js/npm not available)" +elif [[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]]; then echo -e "${GREEN}[OK]${NC} UI build already exists" else - echo -e "${BLUE}[INFO]${NC} Building UI" - pushd "$SCRIPT_DIR/packages/ui" >/dev/null - npm run build - popd >/dev/null - echo -e "${GREEN}[OK]${NC} UI assets built" + echo -e "${BLUE}[INFO]${NC} Building UI (this may take 1-2 minutes)..." + cd "$SCRIPT_DIR/packages/ui" + if npm run build 2>&1; then + echo -e "${GREEN}[OK]${NC} UI assets built successfully" + else + echo -e "${RED}[ERROR]${NC} UI build failed" + log "ERROR: UI build failed" + ERRORS=$((ERRORS+1)) + fi + cd "$SCRIPT_DIR" fi +# ═══════════════════════════════════════════════════════════════ +# STEP 8: Health Check and Summary +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 7/8] Post-install health check" +echo "[STEP 8/8] Running Health Check..." + HEALTH_ERRORS=0 -[[ -f "$SCRIPT_DIR/package.json" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -d "$SCRIPT_DIR/packages/ui" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -d "$SCRIPT_DIR/packages/server" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) +[[ -f "$SCRIPT_DIR/package.json" ]] || { echo -e "${RED}[FAIL]${NC} package.json missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } +[[ -d "$SCRIPT_DIR/packages/ui" ]] || { echo -e "${RED}[FAIL]${NC} packages/ui missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } +[[ -d "$SCRIPT_DIR/packages/server" ]] || { echo -e "${RED}[FAIL]${NC} packages/server missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } + +if [[ $NODE_OK -eq 1 && $NPM_OK -eq 1 ]]; then + [[ -d "$SCRIPT_DIR/node_modules" ]] || { echo -e "${RED}[FAIL]${NC} node_modules missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } + [[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]] || { echo -e "${YELLOW}[WARN]${NC} UI build missing"; ((WARNINGS++)) || true; } +fi if [[ $HEALTH_ERRORS -eq 0 ]]; then echo -e "${GREEN}[OK]${NC} Health checks passed" else - echo -e "${RED}[ERROR]${NC} Health checks failed ($HEALTH_ERRORS)" ERRORS=$((ERRORS+HEALTH_ERRORS)) fi +# Summary echo "" -echo "[STEP 8/8] Installation Summary" +echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║${NC} ${BOLD}INSTALLATION SUMMARY${NC} ${CYAN}║${NC}" +echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" -echo " Install Dir: $TARGET_DIR" -echo " Architecture: $ARCH" -echo " Node.js: $NODE_VERSION" -echo " npm: $NPM_VERSION" -if [[ $BINARY_FREE_MODE -eq 1 ]]; then - echo " Mode: Binary-Free Mode (OpenCode Zen free models available)" -else - echo " Mode: Full Mode (OpenCode binary installed)" -fi -echo " Errors: $ERRORS" -echo " Warnings: $WARNINGS" -echo " Log File: $LOG_FILE" +echo " Install Directory: $TARGET_DIR" +echo " Architecture: $ARCH ($ARCH_TYPE)" +echo " Distribution: $DISTRO_NAME" +[[ -n "${NODE_VERSION:-}" ]] && echo " Node.js: $NODE_VERSION" +[[ -n "${NPM_VERSION:-}" ]] && echo " npm: $NPM_VERSION" +echo " Mode: Binary-Free Mode" +echo " Errors: $ERRORS" +echo " Warnings: $WARNINGS" +echo " Log File: $LOG_FILE" echo "" if [[ $ERRORS -gt 0 ]]; then - echo -e "${RED}[RESULT]${NC} Installation completed with errors" - echo "Review $LOG_FILE for details." -else - echo -e "${GREEN}[RESULT]${NC} Installation completed successfully" - echo "Run: ./Launch-Unix.sh" + echo -e "${RED}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${RED}║${NC} ${BOLD}INSTALLATION COMPLETED WITH ERRORS${NC} ${RED}║${NC}" + echo -e "${RED}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" - if [[ $BINARY_FREE_MODE -eq 1 ]]; then - echo -e "${BLUE}NOTE:${NC} Running in Binary-Free Mode." - echo " Free models (GPT-5 Nano, Grok Code, GLM-4.7, etc.) are available." - echo " You can also authenticate with Qwen for additional models." - fi + echo "Review the errors above and check: $LOG_FILE" + echo "" + echo "Common fixes:" + echo " 1. Install Node.js: sudo apt install nodejs npm" + echo " 2. Run with sudo if permission issues" + echo " 3. Check internet connection" + echo "" + log "Installation FAILED with $ERRORS errors" +else + echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}║${NC} ${BOLD}INSTALLATION SUCCESSFUL!${NC} ${GREEN}║${NC}" + echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" + echo "" + echo "To start NomadArch, run:" + echo " ./Launch-Unix.sh" + echo "" + echo "Available Free Models:" + echo " - GPT-5 Nano (fast)" + echo " - Grok Code (coding)" + echo " - GLM-4.7 (general)" + echo " - Doubao (creative)" + echo "" + log "Installation SUCCESSFUL" fi exit $ERRORS diff --git a/Install-Mac.sh b/Install-Mac.sh index 4aa724f..df3797d 100644 --- a/Install-Mac.sh +++ b/Install-Mac.sh @@ -1,280 +1,413 @@ #!/bin/bash # NomadArch Installer for macOS -# Version: 0.5.0 - Binary-Free Mode +# Version: 0.6.0 - Robust Edition -set -euo pipefail +# Exit on undefined variables +set -u +# Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' +CYAN='\033[0;36m' NC='\033[0m' +BOLD='\033[1m' +# Script directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" TARGET_DIR="$SCRIPT_DIR" BIN_DIR="$TARGET_DIR/bin" LOG_FILE="$TARGET_DIR/install.log" ERRORS=0 WARNINGS=0 -NEEDS_FALLBACK=0 -BINARY_FREE_MODE=0 +BINARY_FREE_MODE=1 +# Logging function log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE" } -echo "" -echo "NomadArch Installer (macOS)" -echo "Version: 0.5.0 - Binary-Free Mode" -echo "" +print_header() { + echo "" + echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${CYAN}║${NC} ${BOLD}NomadArch Installer for macOS${NC} ${CYAN}║${NC}" + echo -e "${CYAN}║${NC} Version: 0.6.0 - Robust Edition ${CYAN}║${NC}" + echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" + echo "" +} -log "Installer started" +print_header +log "========== Installer started ==========" + +# ═══════════════════════════════════════════════════════════════ +# STEP 1: OS and Architecture Detection +# ═══════════════════════════════════════════════════════════════ +echo "[STEP 1/8] Detecting System..." -echo "[STEP 1/8] OS and Architecture Detection" OS_TYPE=$(uname -s) ARCH_TYPE=$(uname -m) -log "OS: $OS_TYPE" -log "Architecture: $ARCH_TYPE" +log "OS: $OS_TYPE, Arch: $ARCH_TYPE" if [[ "$OS_TYPE" != "Darwin" ]]; then echo -e "${RED}[ERROR]${NC} This installer is for macOS. Current OS: $OS_TYPE" + echo " Use Install-Linux.sh for Linux or Install-Windows.bat for Windows." log "ERROR: Not macOS ($OS_TYPE)" exit 1 fi case "$ARCH_TYPE" in - arm64) ARCH="arm64" ;; + arm64) ARCH="arm64" ;; x86_64) ARCH="x64" ;; *) - echo -e "${RED}[ERROR]${NC} Unsupported architecture: $ARCH_TYPE" - log "ERROR: Unsupported arch $ARCH_TYPE" - exit 1 + echo -e "${YELLOW}[WARN]${NC} Unusual architecture: $ARCH_TYPE (proceeding anyway)" + ARCH="$ARCH_TYPE" + ((WARNINGS++)) || true ;; esac -echo -e "${GREEN}[OK]${NC} OS: macOS" -echo -e "${GREEN}[OK]${NC} Architecture: $ARCH_TYPE" +# Get macOS version +MACOS_VERSION=$(sw_vers -productVersion 2>/dev/null || echo "unknown") +echo -e "${GREEN}[OK]${NC} OS: macOS $MACOS_VERSION" +echo -e "${GREEN}[OK]${NC} Architecture: $ARCH_TYPE ($ARCH)" +log "macOS $MACOS_VERSION, Arch: $ARCH_TYPE" + +# ═══════════════════════════════════════════════════════════════ +# STEP 2: Check Write Permissions +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 2/8] Checking write permissions" -mkdir -p "$BIN_DIR" +echo "[STEP 2/8] Checking Write Permissions..." + +mkdir -p "$BIN_DIR" 2>/dev/null || true + if ! touch "$SCRIPT_DIR/.install-write-test" 2>/dev/null; then echo -e "${YELLOW}[WARN]${NC} No write access to $SCRIPT_DIR" - TARGET_DIR="$HOME/.nomadarch-install" + TARGET_DIR="$HOME/.nomadarch" BIN_DIR="$TARGET_DIR/bin" LOG_FILE="$TARGET_DIR/install.log" mkdir -p "$BIN_DIR" if ! touch "$TARGET_DIR/.install-write-test" 2>/dev/null; then echo -e "${RED}[ERROR]${NC} Cannot write to $TARGET_DIR" - log "ERROR: Write permission denied to fallback" + log "ERROR: Write permission denied" exit 1 fi rm -f "$TARGET_DIR/.install-write-test" - NEEDS_FALLBACK=1 echo -e "${GREEN}[OK]${NC} Using fallback: $TARGET_DIR" else rm -f "$SCRIPT_DIR/.install-write-test" - echo -e "${GREEN}[OK]${NC} Write access OK" + echo -e "${GREEN}[OK]${NC} Write access verified" fi - log "Install target: $TARGET_DIR" +# ═══════════════════════════════════════════════════════════════ +# STEP 3: Check Xcode Command Line Tools +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 3/8] Ensuring system dependencies" +echo "[STEP 3/8] Checking Xcode Command Line Tools..." -if ! command -v curl >/dev/null 2>&1; then - echo -e "${RED}[ERROR]${NC} curl is required but not available" - exit 1 +if xcode-select -p >/dev/null 2>&1; then + echo -e "${GREEN}[OK]${NC} Xcode Command Line Tools installed" +else + echo -e "${BLUE}[INFO]${NC} Installing Xcode Command Line Tools..." + echo -e "${YELLOW}[NOTE]${NC} A dialog may appear - click 'Install' to proceed" + xcode-select --install 2>/dev/null || true + + # Wait for installation + echo -e "${BLUE}[INFO]${NC} Waiting for Xcode tools installation..." + while ! xcode-select -p >/dev/null 2>&1; do + sleep 5 + done + echo -e "${GREEN}[OK]${NC} Xcode Command Line Tools installed" fi -if ! command -v brew >/dev/null 2>&1; then - echo -e "${YELLOW}[INFO]${NC} Homebrew not found. Installing..." - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" +# ═══════════════════════════════════════════════════════════════ +# STEP 4: Check and Install Homebrew + Node.js +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 4/8] Checking Homebrew and Node.js..." + +BREW_OK=0 +NODE_OK=0 +NPM_OK=0 + +# Check Homebrew +if command -v brew >/dev/null 2>&1; then + echo -e "${GREEN}[OK]${NC} Homebrew: $(brew --version | head -1)" + BREW_OK=1 +else + echo -e "${BLUE}[INFO]${NC} Homebrew not found. Installing..." + log "Installing Homebrew" + + if /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"; then + # Add Homebrew to PATH for Apple Silicon + if [[ "$ARCH_TYPE" == "arm64" ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" 2>/dev/null || true + echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile 2>/dev/null || true + fi + + # Verify + if command -v brew >/dev/null 2>&1; then + echo -e "${GREEN}[OK]${NC} Homebrew installed successfully" + BREW_OK=1 + else + echo -e "${YELLOW}[WARN]${NC} Homebrew installed but not in PATH" + echo -e "${YELLOW}[INFO]${NC} You may need to restart your terminal" + ((WARNINGS++)) || true + + # Try to find it + if [[ -f "/opt/homebrew/bin/brew" ]]; then + eval "$(/opt/homebrew/bin/brew shellenv)" + BREW_OK=1 + elif [[ -f "/usr/local/bin/brew" ]]; then + eval "$(/usr/local/bin/brew shellenv)" + BREW_OK=1 + fi + fi + else + echo -e "${RED}[ERROR]${NC} Failed to install Homebrew" + log "ERROR: Homebrew installation failed" + ((WARNINGS++)) || true + fi fi -MISSING_PKGS=() -command -v git >/dev/null 2>&1 || MISSING_PKGS+=("git") -command -v node >/dev/null 2>&1 || MISSING_PKGS+=("node") - -if [[ ${#MISSING_PKGS[@]} -gt 0 ]]; then - echo -e "${BLUE}[INFO]${NC} Installing: ${MISSING_PKGS[*]}" - brew install "${MISSING_PKGS[@]}" +# Check Node.js +if command -v node >/dev/null 2>&1; then + NODE_VERSION=$(node --version 2>/dev/null || echo "unknown") + if [[ "$NODE_VERSION" != "unknown" ]]; then + NODE_MAJOR=$(echo "$NODE_VERSION" | sed 's/v//' | cut -d'.' -f1) + echo -e "${GREEN}[OK]${NC} Node.js: $NODE_VERSION" + NODE_OK=1 + + if [[ $NODE_MAJOR -lt 18 ]]; then + echo -e "${YELLOW}[WARN]${NC} Node.js 18+ recommended (current: $NODE_VERSION)" + ((WARNINGS++)) || true + fi + fi fi -if ! command -v node >/dev/null 2>&1; then - echo -e "${RED}[ERROR]${NC} Node.js install failed" - exit 1 +# Install Node.js if needed +if [[ $NODE_OK -eq 0 ]]; then + echo -e "${BLUE}[INFO]${NC} Node.js not found. Installing..." + log "Installing Node.js" + + INSTALL_SUCCESS=0 + + # Try Homebrew first + if [[ $BREW_OK -eq 1 ]]; then + if brew install node 2>&1; then + INSTALL_SUCCESS=1 + fi + fi + + # Try nvm as fallback + if [[ $INSTALL_SUCCESS -eq 0 ]]; then + echo -e "${BLUE}[INFO]${NC} Trying nvm installation..." + export NVM_DIR="$HOME/.nvm" + if curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh 2>/dev/null | bash >/dev/null 2>&1; then + [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" + if nvm install 20 2>&1; then + INSTALL_SUCCESS=1 + fi + fi + fi + + # Try official pkg installer as last resort + if [[ $INSTALL_SUCCESS -eq 0 ]]; then + echo -e "${BLUE}[INFO]${NC} Downloading Node.js installer..." + NODE_PKG="/tmp/node-installer.pkg" + if curl -fsSL "https://nodejs.org/dist/v20.10.0/node-v20.10.0.pkg" -o "$NODE_PKG" 2>/dev/null; then + echo -e "${BLUE}[INFO]${NC} Running Node.js installer (may require password)..." + sudo installer -pkg "$NODE_PKG" -target / && INSTALL_SUCCESS=1 + rm -f "$NODE_PKG" + fi + fi + + if [[ $INSTALL_SUCCESS -eq 1 ]]; then + # Verify installation + hash -r 2>/dev/null || true + if command -v node >/dev/null 2>&1; then + NODE_VERSION=$(node --version) + echo -e "${GREEN}[OK]${NC} Node.js installed: $NODE_VERSION" + NODE_OK=1 + fi + fi + + if [[ $NODE_OK -eq 0 ]]; then + echo -e "${RED}[ERROR]${NC} Could not install Node.js automatically" + echo "" + echo "Please install Node.js manually:" + echo " 1. Install via Homebrew: brew install node" + echo " 2. Or download from: https://nodejs.org/" + echo "" + log "ERROR: Node.js installation failed" + ERRORS=$((ERRORS+1)) + fi fi -NODE_VERSION=$(node --version) -NODE_MAJOR=$(echo "$NODE_VERSION" | cut -d'v' -f2 | cut -d'.' -f1) -echo -e "${GREEN}[OK]${NC} Node.js: $NODE_VERSION" -if [[ $NODE_MAJOR -lt 18 ]]; then - echo -e "${YELLOW}[WARN]${NC} Node.js 18+ is recommended" - ((WARNINGS++)) +# Check npm +if command -v npm >/dev/null 2>&1; then + NPM_VERSION=$(npm --version 2>/dev/null || echo "unknown") + if [[ "$NPM_VERSION" != "unknown" ]]; then + echo -e "${GREEN}[OK]${NC} npm: $NPM_VERSION" + NPM_OK=1 + fi fi -if ! command -v npm >/dev/null 2>&1; then - echo -e "${RED}[ERROR]${NC} npm is not available" - exit 1 +if [[ $NPM_OK -eq 0 && $NODE_OK -eq 1 ]]; then + echo -e "${RED}[ERROR]${NC} npm not found (should come with Node.js)" + ERRORS=$((ERRORS+1)) fi -NPM_VERSION=$(npm --version) -echo -e "${GREEN}[OK]${NC} npm: $NPM_VERSION" + +# ═══════════════════════════════════════════════════════════════ +# STEP 5: Check Git (optional) +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 5/8] Checking Optional Dependencies..." if command -v git >/dev/null 2>&1; then echo -e "${GREEN}[OK]${NC} Git: $(git --version)" else - echo -e "${YELLOW}[WARN]${NC} Git not found (optional)" - ((WARNINGS++)) + echo -e "${YELLOW}[INFO]${NC} Git not found (optional - installing via Homebrew)" + if [[ $BREW_OK -eq 1 ]]; then + brew install git 2>/dev/null || true + fi fi -echo "" -echo "[STEP 4/8] Installing npm dependencies" -cd "$SCRIPT_DIR" -log "Running npm install" -if ! npm install; then - echo -e "${RED}[ERROR]${NC} npm install failed" - log "ERROR: npm install failed" - exit 1 -fi - -echo -e "${GREEN}[OK]${NC} Dependencies installed" - -echo "" -echo "[STEP 5/8] OpenCode Binary (OPTIONAL - Binary-Free Mode Available)" -echo -e "${BLUE}[INFO]${NC} NomadArch now supports Binary-Free Mode!" -echo -e "${BLUE}[INFO]${NC} You can use the application without OpenCode binary." -echo -e "${BLUE}[INFO]${NC} Free models from OpenCode Zen are available without the binary." -mkdir -p "$BIN_DIR" - -echo "" -read -p "Skip OpenCode binary download? (Y for Binary-Free Mode / N to download) [Y]: " SKIP_CHOICE -SKIP_CHOICE="${SKIP_CHOICE:-Y}" - -if [[ "${SKIP_CHOICE^^}" == "Y" ]]; then - BINARY_FREE_MODE=1 - echo -e "${GREEN}[INFO]${NC} Skipping OpenCode binary - using Binary-Free Mode" - log "Using Binary-Free Mode" +if command -v curl >/dev/null 2>&1; then + echo -e "${GREEN}[OK]${NC} curl: available" else - # Pin to a specific known-working version - OPENCODE_PINNED_VERSION="0.1.44" - OPENCODE_VERSION="$OPENCODE_PINNED_VERSION" + echo -e "${RED}[ERROR]${NC} curl not found (required)" + ERRORS=$((ERRORS+1)) +fi - LATEST_VERSION=$(curl -s --max-time 10 https://api.github.com/repos/sst/opencode/releases/latest 2>/dev/null | grep '"tag_name"' | cut -d'"' -f4 | sed 's/^v//') - if [[ -n "$LATEST_VERSION" ]]; then - echo -e "${BLUE}[INFO]${NC} Latest available: v${LATEST_VERSION}, using pinned: v${OPENCODE_VERSION}" - fi +# ═══════════════════════════════════════════════════════════════ +# STEP 6: Install npm Dependencies +# ═══════════════════════════════════════════════════════════════ +echo "" +echo "[STEP 6/8] Installing Dependencies..." - OPENCODE_BASE="https://github.com/sst/opencode/releases/download/v${OPENCODE_VERSION}" - OPENCODE_URL="${OPENCODE_BASE}/opencode-darwin-${ARCH}" - CHECKSUM_URL="${OPENCODE_BASE}/checksums.txt" - - NEEDS_DOWNLOAD=0 - if [[ -f "$BIN_DIR/opencode" ]]; then - EXISTING_VERSION=$("$BIN_DIR/opencode" --version 2>/dev/null | head -1 || echo "unknown") - if [[ "$EXISTING_VERSION" == *"$OPENCODE_VERSION"* ]] || [[ "$EXISTING_VERSION" != "unknown" ]]; then - echo -e "${GREEN}[OK]${NC} OpenCode binary exists (version: $EXISTING_VERSION)" - else - echo -e "${YELLOW}[WARN]${NC} Existing binary version mismatch, re-downloading..." - NEEDS_DOWNLOAD=1 - fi +if [[ $NODE_OK -eq 0 || $NPM_OK -eq 0 ]]; then + echo -e "${YELLOW}[SKIP]${NC} Skipping npm install (Node.js/npm not available)" +else + cd "$SCRIPT_DIR" + + if [[ ! -f "package.json" ]]; then + echo -e "${RED}[ERROR]${NC} package.json not found in $SCRIPT_DIR" + echo "Make sure you extracted the full NomadArch package." + log "ERROR: package.json missing" + ERRORS=$((ERRORS+1)) else - NEEDS_DOWNLOAD=1 - fi - - if [[ $NEEDS_DOWNLOAD -eq 1 ]]; then - echo -e "${BLUE}[INFO]${NC} Downloading OpenCode v${OPENCODE_VERSION} for ${ARCH}..." + echo -e "${BLUE}[INFO]${NC} Running npm install (this may take a few minutes)..." + log "Running npm install" - DOWNLOAD_SUCCESS=0 - for attempt in 1 2 3; do - if curl -L --fail --retry 3 -o "$BIN_DIR/opencode.tmp" "$OPENCODE_URL" 2>/dev/null; then - DOWNLOAD_SUCCESS=1 - break - fi - echo -e "${YELLOW}[WARN]${NC} Download attempt $attempt failed, retrying..." - sleep 2 - done - - if [[ $DOWNLOAD_SUCCESS -eq 0 ]]; then - echo -e "${YELLOW}[WARN]${NC} Failed to download OpenCode binary - using Binary-Free Mode" - BINARY_FREE_MODE=1 + if npm install --no-audit --no-fund 2>&1; then + echo -e "${GREEN}[OK]${NC} Dependencies installed" else - if curl -L --fail -o "$BIN_DIR/checksums.txt" "$CHECKSUM_URL" 2>/dev/null; then - EXPECTED_HASH=$(grep "opencode-darwin-${ARCH}" "$BIN_DIR/checksums.txt" | awk '{print $1}') - ACTUAL_HASH=$(shasum -a 256 "$BIN_DIR/opencode.tmp" | awk '{print $1}') - - if [[ "$ACTUAL_HASH" == "$EXPECTED_HASH" ]]; then - echo -e "${GREEN}[OK]${NC} Checksum verified" - else - echo -e "${YELLOW}[WARN]${NC} Checksum mismatch (may be OK for some versions)" - fi + echo -e "${YELLOW}[WARN]${NC} npm install had issues, trying with legacy peer deps..." + if npm install --legacy-peer-deps --no-audit --no-fund 2>&1; then + echo -e "${GREEN}[OK]${NC} Dependencies installed (with legacy peer deps)" + else + echo -e "${RED}[ERROR]${NC} npm install failed" + log "ERROR: npm install failed" + ERRORS=$((ERRORS+1)) fi - - mv "$BIN_DIR/opencode.tmp" "$BIN_DIR/opencode" - chmod +x "$BIN_DIR/opencode" - echo -e "${GREEN}[OK]${NC} OpenCode binary installed" fi fi fi +# ═══════════════════════════════════════════════════════════════ +# STEP 7: Build UI Assets +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 6/8] Building UI assets" -if [[ -d "$SCRIPT_DIR/packages/ui/dist" ]]; then +echo "[STEP 7/8] Building UI Assets..." + +if [[ $NODE_OK -eq 0 || $NPM_OK -eq 0 ]]; then + echo -e "${YELLOW}[SKIP]${NC} Skipping UI build (Node.js/npm not available)" +elif [[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]]; then echo -e "${GREEN}[OK]${NC} UI build already exists" else - echo -e "${BLUE}[INFO]${NC} Building UI" - pushd "$SCRIPT_DIR/packages/ui" >/dev/null - npm run build - popd >/dev/null - echo -e "${GREEN}[OK]${NC} UI assets built" + echo -e "${BLUE}[INFO]${NC} Building UI (this may take 1-2 minutes)..." + cd "$SCRIPT_DIR/packages/ui" + if npm run build 2>&1; then + echo -e "${GREEN}[OK]${NC} UI assets built successfully" + else + echo -e "${RED}[ERROR]${NC} UI build failed" + log "ERROR: UI build failed" + ERRORS=$((ERRORS+1)) + fi + cd "$SCRIPT_DIR" fi +# ═══════════════════════════════════════════════════════════════ +# STEP 8: Health Check and Summary +# ═══════════════════════════════════════════════════════════════ echo "" -echo "[STEP 7/8] Post-install health check" +echo "[STEP 8/8] Running Health Check..." + HEALTH_ERRORS=0 -[[ -f "$SCRIPT_DIR/package.json" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -d "$SCRIPT_DIR/packages/ui" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -d "$SCRIPT_DIR/packages/server" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) -[[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]] || HEALTH_ERRORS=$((HEALTH_ERRORS+1)) +[[ -f "$SCRIPT_DIR/package.json" ]] || { echo -e "${RED}[FAIL]${NC} package.json missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } +[[ -d "$SCRIPT_DIR/packages/ui" ]] || { echo -e "${RED}[FAIL]${NC} packages/ui missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } +[[ -d "$SCRIPT_DIR/packages/server" ]] || { echo -e "${RED}[FAIL]${NC} packages/server missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } + +if [[ $NODE_OK -eq 1 && $NPM_OK -eq 1 ]]; then + [[ -d "$SCRIPT_DIR/node_modules" ]] || { echo -e "${RED}[FAIL]${NC} node_modules missing"; HEALTH_ERRORS=$((HEALTH_ERRORS+1)); } + [[ -f "$SCRIPT_DIR/packages/ui/dist/index.html" ]] || { echo -e "${YELLOW}[WARN]${NC} UI build missing"; ((WARNINGS++)) || true; } +fi if [[ $HEALTH_ERRORS -eq 0 ]]; then echo -e "${GREEN}[OK]${NC} Health checks passed" else - echo -e "${RED}[ERROR]${NC} Health checks failed ($HEALTH_ERRORS)" ERRORS=$((ERRORS+HEALTH_ERRORS)) fi +# Summary echo "" -echo "[STEP 8/8] Installation Summary" +echo -e "${CYAN}╔═══════════════════════════════════════════════════════════════╗${NC}" +echo -e "${CYAN}║${NC} ${BOLD}INSTALLATION SUMMARY${NC} ${CYAN}║${NC}" +echo -e "${CYAN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" -echo " Install Dir: $TARGET_DIR" -echo " Architecture: $ARCH" -echo " Node.js: $NODE_VERSION" -echo " npm: $NPM_VERSION" -if [[ $BINARY_FREE_MODE -eq 1 ]]; then - echo " Mode: Binary-Free Mode (OpenCode Zen free models available)" -else - echo " Mode: Full Mode (OpenCode binary installed)" -fi -echo " Errors: $ERRORS" -echo " Warnings: $WARNINGS" -echo " Log File: $LOG_FILE" +echo " Install Directory: $TARGET_DIR" +echo " Architecture: $ARCH ($ARCH_TYPE)" +echo " macOS Version: $MACOS_VERSION" +[[ -n "${NODE_VERSION:-}" ]] && echo " Node.js: $NODE_VERSION" +[[ -n "${NPM_VERSION:-}" ]] && echo " npm: $NPM_VERSION" +echo " Mode: Binary-Free Mode" +echo " Errors: $ERRORS" +echo " Warnings: $WARNINGS" +echo " Log File: $LOG_FILE" echo "" if [[ $ERRORS -gt 0 ]]; then - echo -e "${RED}[RESULT]${NC} Installation completed with errors" - echo "Review $LOG_FILE for details." -else - echo -e "${GREEN}[RESULT]${NC} Installation completed successfully" - echo "Run: ./Launch-Unix.sh" + echo -e "${RED}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${RED}║${NC} ${BOLD}INSTALLATION COMPLETED WITH ERRORS${NC} ${RED}║${NC}" + echo -e "${RED}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" - if [[ $BINARY_FREE_MODE -eq 1 ]]; then - echo -e "${BLUE}NOTE:${NC} Running in Binary-Free Mode." - echo " Free models (GPT-5 Nano, Grok Code, GLM-4.7, etc.) are available." - echo " You can also authenticate with Qwen for additional models." - fi + echo "Review the errors above and check: $LOG_FILE" + echo "" + echo "Common fixes:" + echo " 1. Install Homebrew: /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" + echo " 2. Install Node.js: brew install node" + echo " 3. Restart terminal after Homebrew installation" + echo "" + log "Installation FAILED with $ERRORS errors" +else + echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" + echo -e "${GREEN}║${NC} ${BOLD}INSTALLATION SUCCESSFUL!${NC} ${GREEN}║${NC}" + echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" + echo "" + echo "To start NomadArch, run:" + echo " ./Launch-Unix.sh" + echo "" + echo "Available Free Models:" + echo " - GPT-5 Nano (fast)" + echo " - Grok Code (coding)" + echo " - GLM-4.7 (general)" + echo " - Doubao (creative)" + echo "" + log "Installation SUCCESSFUL" fi exit $ERRORS diff --git a/Install-Windows.bat b/Install-Windows.bat index f472a56..cab7e01 100644 --- a/Install-Windows.bat +++ b/Install-Windows.bat @@ -1,11 +1,14 @@ @echo off +chcp 65001 >nul 2>&1 setlocal enabledelayedexpansion -title NomadArch Installer +title NomadArch Installer - Windows echo. -echo NomadArch Installer (Windows) -echo Version: 0.5.0 - Binary-Free Mode +echo ╔═══════════════════════════════════════════════════════════════╗ +echo ║ NomadArch Installer for Windows ║ +echo ║ Version: 0.6.0 - Robust Edition ║ +echo ╚═══════════════════════════════════════════════════════════════╝ echo. set SCRIPT_DIR=%~dp0 @@ -17,192 +20,256 @@ set TEMP_DIR=%TARGET_DIR%\.install-temp set ERRORS=0 set WARNINGS=0 -set NEEDS_FALLBACK=0 -set SKIP_OPENCODE=0 +set SKIP_OPENCODE=1 +set NODE_INSTALLED_NOW=0 -echo [%date% %time%] Installer started >> "%LOG_FILE%" +echo [%date% %time%] ========== Installer started ========== >> "%LOG_FILE%" -echo [STEP 1/8] OS and Architecture Detection +REM ═══════════════════════════════════════════════════════════════ +REM STEP 1: OS and Architecture Detection +REM ═══════════════════════════════════════════════════════════════ +echo [STEP 1/8] Detecting System... -REM Use PowerShell for architecture detection (works on all Windows versions) -for /f "tokens=*" %%i in ('powershell -NoProfile -Command "[System.Environment]::Is64BitOperatingSystem"') do set IS64BIT=%%i -if /i "%IS64BIT%"=="True" ( +for /f "tokens=2 delims==" %%a in ('wmic os get osarchitecture /value 2^>nul ^| find "="') do set ARCH_RAW=%%a +if "!ARCH_RAW!"=="" set ARCH_RAW=64-bit + +echo !ARCH_RAW! | findstr /i "64" >nul +if !ERRORLEVEL! equ 0 ( set ARCH=x64 ) else ( set ARCH=x86 ) -echo [OK] Architecture: %ARCH% +for /f "tokens=4-5 delims=. " %%i in ('ver') do set WIN_VER=%%i.%%j +echo [OK] Windows Version: !WIN_VER! +echo [OK] Architecture: !ARCH! +echo [%date% %time%] OS: Windows !WIN_VER!, Arch: !ARCH! >> "%LOG_FILE%" + +REM ═══════════════════════════════════════════════════════════════ +REM STEP 2: Check Write Permissions +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 2/8] Checking write permissions +echo [STEP 2/8] Checking Write Permissions... + if not exist "%BIN_DIR%" mkdir "%BIN_DIR%" 2>nul if not exist "%TEMP_DIR%" mkdir "%TEMP_DIR%" 2>nul -echo. > "%SCRIPT_DIR%\test-write.tmp" 2>nul +echo. > "%SCRIPT_DIR%\.write-test.tmp" 2>nul if !ERRORLEVEL! neq 0 ( - echo [WARN] Cannot write to current directory: %SCRIPT_DIR% - set TARGET_DIR=%USERPROFILE%\NomadArch-Install + echo [WARN] Cannot write to: %SCRIPT_DIR% + echo [INFO] Using fallback location in user profile... + set TARGET_DIR=%USERPROFILE%\NomadArch set BIN_DIR=!TARGET_DIR!\bin set LOG_FILE=!TARGET_DIR!\install.log set TEMP_DIR=!TARGET_DIR!\.install-temp if not exist "!TARGET_DIR!" mkdir "!TARGET_DIR!" if not exist "!BIN_DIR!" mkdir "!BIN_DIR!" if not exist "!TEMP_DIR!" mkdir "!TEMP_DIR!" - echo. > "!TARGET_DIR!\test-write.tmp" 2>nul - if !ERRORLEVEL! neq 0 ( - echo [ERROR] Cannot write to fallback directory: !TARGET_DIR! - echo [%date% %time%] ERROR: Write permission denied >> "%LOG_FILE%" - set /a ERRORS+=1 - goto :SUMMARY - ) - del "!TARGET_DIR!\test-write.tmp" - set NEEDS_FALLBACK=1 echo [OK] Using fallback: !TARGET_DIR! ) else ( - del "%SCRIPT_DIR%\test-write.tmp" + del "%SCRIPT_DIR%\.write-test.tmp" 2>nul echo [OK] Write permissions verified ) +echo [%date% %time%] Install target: %TARGET_DIR% >> "%LOG_FILE%" +REM ═══════════════════════════════════════════════════════════════ +REM STEP 3: Check and Install Node.js +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 3/8] Ensuring system dependencies +echo [STEP 3/8] Checking Node.js... -set WINGET_AVAILABLE=0 -where winget >nul 2>&1 -if !ERRORLEVEL! equ 0 set WINGET_AVAILABLE=1 - -set CHOCO_AVAILABLE=0 -where choco >nul 2>&1 -if !ERRORLEVEL! equ 0 set CHOCO_AVAILABLE=1 - -set DOWNLOAD_CMD=powershell -where curl >nul 2>&1 -if !ERRORLEVEL! equ 0 set DOWNLOAD_CMD=curl +set NODE_OK=0 +set NPM_OK=0 where node >nul 2>&1 -if !ERRORLEVEL! neq 0 ( - echo [INFO] Node.js not found. Attempting to install... - if !WINGET_AVAILABLE! equ 1 ( - winget install -e --id OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements - ) else if !CHOCO_AVAILABLE! equ 1 ( - choco install nodejs-lts -y +if !ERRORLEVEL! equ 0 ( + for /f "tokens=*" %%v in ('node --version 2^>nul') do set NODE_VERSION=%%v + if defined NODE_VERSION ( + echo [OK] Node.js found: !NODE_VERSION! + set NODE_OK=1 + ) +) + +if !NODE_OK! equ 0 ( + echo [INFO] Node.js not found. Attempting automatic installation... + echo [%date% %time%] Node.js not found, attempting install >> "%LOG_FILE%" + + REM Try winget first (Windows 10 1709+) + where winget >nul 2>&1 + if !ERRORLEVEL! equ 0 ( + echo [INFO] Installing Node.js via winget... + winget install -e --id OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements --silent + if !ERRORLEVEL! equ 0 ( + set NODE_INSTALLED_NOW=1 + echo [OK] Node.js installed via winget + ) else ( + echo [WARN] Winget install failed, trying alternative... + ) + ) + + REM Try chocolatey if winget failed + if !NODE_INSTALLED_NOW! equ 0 ( + where choco >nul 2>&1 + if !ERRORLEVEL! equ 0 ( + echo [INFO] Installing Node.js via Chocolatey... + choco install nodejs-lts -y + if !ERRORLEVEL! equ 0 ( + set NODE_INSTALLED_NOW=1 + echo [OK] Node.js installed via Chocolatey + ) + ) + ) + + REM Direct download as last resort + if !NODE_INSTALLED_NOW! equ 0 ( + echo [INFO] Downloading Node.js installer directly... + set NODE_INSTALLER=%TEMP_DIR%\node-installer.msi + + REM Download using PowerShell + powershell -NoProfile -ExecutionPolicy Bypass -Command ^ + "$ProgressPreference = 'SilentlyContinue'; " ^ + "try { " ^ + " Invoke-WebRequest -Uri 'https://nodejs.org/dist/v20.10.0/node-v20.10.0-x64.msi' -OutFile '%TEMP_DIR%\node-installer.msi' -UseBasicParsing; " ^ + " exit 0 " ^ + "} catch { exit 1 }" + + if exist "%TEMP_DIR%\node-installer.msi" ( + echo [INFO] Running Node.js installer... + msiexec /i "%TEMP_DIR%\node-installer.msi" /qn /norestart + if !ERRORLEVEL! equ 0 ( + set NODE_INSTALLED_NOW=1 + echo [OK] Node.js installed successfully + ) else ( + echo [ERROR] Node.js MSI installation failed + ) + del "%TEMP_DIR%\node-installer.msi" 2>nul + ) else ( + echo [ERROR] Failed to download Node.js installer + ) + ) + + if !NODE_INSTALLED_NOW! equ 1 ( + echo. + echo ╔═══════════════════════════════════════════════════════════════╗ + echo ║ IMPORTANT: Node.js was just installed! ║ + echo ║ Please CLOSE this window and run Install-Windows.bat again. ║ + echo ║ This is required for the PATH to update. ║ + echo ╚═══════════════════════════════════════════════════════════════╝ + echo. + echo [%date% %time%] Node.js installed, restart required >> "%LOG_FILE%" + pause + exit /b 0 ) else ( - echo [ERROR] No supported package manager found. - echo Please install Node.js LTS from https://nodejs.org/ + echo. + echo [ERROR] Could not install Node.js automatically. + echo. + echo Please install Node.js manually: + echo 1. Go to https://nodejs.org/ + echo 2. Download and install the LTS version + echo 3. Restart this installer + echo. + echo [%date% %time%] ERROR: Node.js installation failed >> "%LOG_FILE%" set /a ERRORS+=1 goto :SUMMARY ) ) -where node >nul 2>&1 -if !ERRORLEVEL! neq 0 ( - echo [ERROR] Node.js install failed or requires a new terminal session. - set /a ERRORS+=1 - goto :SUMMARY -) - -for /f "tokens=*" %%i in ('node --version') do set NODE_VERSION=%%i -echo [OK] Node.js: %NODE_VERSION% - +REM Verify npm where npm >nul 2>&1 -if !ERRORLEVEL! neq 0 ( - echo [ERROR] npm not found after Node.js install. +if !ERRORLEVEL! equ 0 ( + for /f "tokens=*" %%v in ('npm --version 2^>nul') do set NPM_VERSION=%%v + if defined NPM_VERSION ( + echo [OK] npm found: !NPM_VERSION! + set NPM_OK=1 + ) +) + +if !NPM_OK! equ 0 ( + echo [ERROR] npm not found. This usually comes with Node.js. + echo [%date% %time%] ERROR: npm not found >> "%LOG_FILE%" set /a ERRORS+=1 goto :SUMMARY ) -for /f "tokens=*" %%i in ('npm --version') do set NPM_VERSION=%%i -echo [OK] npm: %NPM_VERSION% +REM ═══════════════════════════════════════════════════════════════ +REM STEP 4: Check Git (optional) +REM ═══════════════════════════════════════════════════════════════ +echo. +echo [STEP 4/8] Checking Git (optional)... where git >nul 2>&1 -if !ERRORLEVEL! neq 0 ( - echo [INFO] Git not found. Attempting to install... - if !WINGET_AVAILABLE! equ 1 ( - winget install -e --id Git.Git --accept-source-agreements --accept-package-agreements - ) else if !CHOCO_AVAILABLE! equ 1 ( - choco install git -y - ) else ( - echo [WARN] Git not installed - optional - set /a WARNINGS+=1 - ) +if !ERRORLEVEL! equ 0 ( + for /f "tokens=*" %%v in ('git --version 2^>nul') do set GIT_VERSION=%%v + echo [OK] !GIT_VERSION! ) else ( - for /f "tokens=*" %%i in ('git --version') do set GIT_VERSION=%%i - echo [OK] Git: !GIT_VERSION! + echo [INFO] Git not found (optional - not required for basic usage) + set /a WARNINGS+=1 ) +REM ═══════════════════════════════════════════════════════════════ +REM STEP 5: Install npm Dependencies +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 4/8] Installing npm dependencies +echo [STEP 5/8] Installing Dependencies... + cd /d "%SCRIPT_DIR%" -echo [%date% %time%] Running npm install >> "%LOG_FILE%" -call npm install -if !ERRORLEVEL! neq 0 ( - echo [ERROR] npm install failed! - echo [%date% %time%] ERROR: npm install failed >> "%LOG_FILE%" + +if not exist "package.json" ( + echo [ERROR] package.json not found in %SCRIPT_DIR% + echo [ERROR] Make sure you extracted the full NomadArch package. + echo [%date% %time%] ERROR: package.json missing >> "%LOG_FILE%" set /a ERRORS+=1 goto :SUMMARY ) + +echo [INFO] Running npm install (this may take a few minutes)... +echo [%date% %time%] Running npm install >> "%LOG_FILE%" + +call npm install --no-audit --no-fund 2>&1 +if !ERRORLEVEL! neq 0 ( + echo [WARN] npm install had issues, trying with legacy peer deps... + call npm install --legacy-peer-deps --no-audit --no-fund 2>&1 + if !ERRORLEVEL! neq 0 ( + echo [ERROR] npm install failed! + echo [%date% %time%] ERROR: npm install failed >> "%LOG_FILE%" + set /a ERRORS+=1 + goto :SUMMARY + ) +) echo [OK] Dependencies installed +REM ═══════════════════════════════════════════════════════════════ +REM STEP 6: OpenCode Binary (OPTIONAL) +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 5/8] OpenCode Binary - OPTIONAL +echo [STEP 6/8] OpenCode Binary Setup... echo. -echo [INFO] NomadArch now supports Binary-Free Mode! -echo [INFO] You can use the application without OpenCode binary. -echo [INFO] Free models from OpenCode Zen are available without the binary. +echo ╔═══════════════════════════════════════════════════════════════╗ +echo ║ NomadArch supports Binary-Free Mode! ║ +echo ║ You can skip the OpenCode binary and use free cloud models: ║ +echo ║ - GPT-5 Nano, Grok Code, GLM-4.7, Doubao, and more ║ +echo ╚═══════════════════════════════════════════════════════════════╝ echo. -if not exist "%BIN_DIR%" mkdir "%BIN_DIR%" 2>nul -set /p SKIP_CHOICE="Skip OpenCode binary download? (Y for Binary-Free / N to download) [Y]: " -if /i "!SKIP_CHOICE!"=="" set SKIP_CHOICE=Y -if /i "!SKIP_CHOICE!"=="Y" goto :skip_opencode_download - -REM Download OpenCode binary -echo [INFO] Fetching OpenCode version info... -for /f "delims=" %%v in ('powershell -NoProfile -Command "try { (Invoke-WebRequest -UseBasicParsing https://api.github.com/repos/sst/opencode/releases/latest).Content | ConvertFrom-Json | Select-Object -ExpandProperty tag_name } catch { 'v0.1.44' }"') do set OPENCODE_VERSION=%%v -set OPENCODE_VERSION=!OPENCODE_VERSION:v=! - -set OPENCODE_BASE=https://github.com/sst/opencode/releases/download/v!OPENCODE_VERSION! -set OPENCODE_URL=!OPENCODE_BASE!/opencode-windows-%ARCH%.exe -set CHECKSUM_URL=!OPENCODE_BASE!/checksums.txt - -if exist "%BIN_DIR%\opencode.exe" ( - echo [OK] OpenCode binary already exists - echo [%date% %time%] OpenCode binary exists, skipping download >> "%LOG_FILE%" - goto :opencode_done -) - -echo [INFO] Downloading OpenCode v!OPENCODE_VERSION!... -if "!DOWNLOAD_CMD!"=="curl" ( - curl -L -o "%BIN_DIR%\opencode.exe.tmp" "!OPENCODE_URL!" -) else ( - powershell -NoProfile -Command "Invoke-WebRequest -Uri '!OPENCODE_URL!' -OutFile '%BIN_DIR%\opencode.exe.tmp'" -) - -if exist "%BIN_DIR%\opencode.exe.tmp" ( - move /Y "%BIN_DIR%\opencode.exe.tmp" "%BIN_DIR%\opencode.exe" >nul - echo [OK] OpenCode downloaded -) else ( - echo [WARN] OpenCode download failed - using Binary-Free Mode instead - set SKIP_OPENCODE=1 -) -goto :opencode_done - -:skip_opencode_download set SKIP_OPENCODE=1 -echo [INFO] Skipping OpenCode binary - using Binary-Free Mode +echo [OK] Using Binary-Free Mode (default) echo [%date% %time%] Using Binary-Free Mode >> "%LOG_FILE%" -:opencode_done - +REM ═══════════════════════════════════════════════════════════════ +REM STEP 7: Build UI Assets +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 6/8] Building UI assets +echo [STEP 7/8] Building UI Assets... + if exist "%SCRIPT_DIR%\packages\ui\dist\index.html" ( echo [OK] UI build already exists ) else ( - echo [INFO] Building UI assets... - pushd packages\ui - call npm run build + echo [INFO] Building UI (this may take 1-2 minutes)... + pushd "%SCRIPT_DIR%\packages\ui" + call npm run build 2>&1 if !ERRORLEVEL! neq 0 ( echo [ERROR] UI build failed! + echo [%date% %time%] ERROR: UI build failed >> "%LOG_FILE%" popd set /a ERRORS+=1 goto :SUMMARY @@ -211,54 +278,92 @@ if exist "%SCRIPT_DIR%\packages\ui\dist\index.html" ( echo [OK] UI assets built successfully ) +REM ═══════════════════════════════════════════════════════════════ +REM STEP 8: Health Check and Summary +REM ═══════════════════════════════════════════════════════════════ echo. -echo [STEP 7/8] Post-install health check -set HEALTH_ERRORS=0 +echo [STEP 8/8] Running Health Check... -if not exist "%SCRIPT_DIR%\package.json" set /a HEALTH_ERRORS+=1 -if not exist "%SCRIPT_DIR%\packages\ui" set /a HEALTH_ERRORS+=1 -if not exist "%SCRIPT_DIR%\packages\server" set /a HEALTH_ERRORS+=1 -if not exist "%SCRIPT_DIR%\packages\ui\dist\index.html" set /a HEALTH_ERRORS+=1 +set HEALTH_OK=1 -if !HEALTH_ERRORS! equ 0 ( - echo [OK] Health checks passed -) else ( - echo [ERROR] Health checks failed: !HEALTH_ERRORS! issues - set /a ERRORS+=!HEALTH_ERRORS! +if not exist "%SCRIPT_DIR%\package.json" ( + echo [FAIL] package.json missing + set HEALTH_OK=0 ) -echo. -echo [STEP 8/8] Installation Summary -echo. -echo Install Dir: %TARGET_DIR% -echo Architecture: %ARCH% -echo Node.js: %NODE_VERSION% -echo npm: %NPM_VERSION% -if !SKIP_OPENCODE! equ 1 ( - echo Mode: Binary-Free Mode -) else ( - echo Mode: Full Mode with OpenCode binary +if not exist "%SCRIPT_DIR%\packages\ui" ( + echo [FAIL] packages\ui directory missing + set HEALTH_OK=0 +) + +if not exist "%SCRIPT_DIR%\packages\server" ( + echo [FAIL] packages\server directory missing + set HEALTH_OK=0 +) + +if not exist "%SCRIPT_DIR%\packages\ui\dist\index.html" ( + echo [FAIL] UI build missing (packages\ui\dist\index.html) + set HEALTH_OK=0 +) + +if not exist "%SCRIPT_DIR%\node_modules" ( + echo [FAIL] node_modules directory missing + set HEALTH_OK=0 +) + +if !HEALTH_OK! equ 1 ( + echo [OK] All health checks passed +) else ( + echo [ERROR] Health checks failed + set /a ERRORS+=1 ) -echo Errors: !ERRORS! -echo Warnings: !WARNINGS! -echo Log File: %LOG_FILE% -echo. :SUMMARY +echo. +echo ╔═══════════════════════════════════════════════════════════════╗ +echo ║ INSTALLATION SUMMARY ║ +echo ╚═══════════════════════════════════════════════════════════════╝ +echo. +echo Install Directory: %TARGET_DIR% +echo Architecture: !ARCH! +if defined NODE_VERSION echo Node.js: !NODE_VERSION! +if defined NPM_VERSION echo npm: !NPM_VERSION! +echo Mode: Binary-Free Mode +echo Errors: !ERRORS! +echo Warnings: !WARNINGS! +echo Log File: %LOG_FILE% +echo. + if !ERRORS! gtr 0 ( - echo [RESULT] Installation completed with errors. - echo Review the log: %LOG_FILE% + echo ╔═══════════════════════════════════════════════════════════════╗ + echo ║ INSTALLATION FAILED ║ + echo ╚═══════════════════════════════════════════════════════════════╝ echo. - echo If Node.js was just installed, open a new terminal and run this installer again. + echo Review the errors above and check the log file: %LOG_FILE% + echo. + echo Common fixes: + echo 1. Run as Administrator (right-click, Run as administrator) + echo 2. Ensure internet connection is stable + echo 3. Disable antivirus temporarily + echo 4. Install Node.js manually from https://nodejs.org/ + echo. + echo [%date% %time%] Installation FAILED with !ERRORS! errors >> "%LOG_FILE%" ) else ( - echo [RESULT] Installation completed successfully. - echo Run Launch-Windows.bat to start the application. + echo ╔═══════════════════════════════════════════════════════════════╗ + echo ║ INSTALLATION SUCCESSFUL! ║ + echo ╚═══════════════════════════════════════════════════════════════╝ echo. - if !SKIP_OPENCODE! equ 1 ( - echo NOTE: Running in Binary-Free Mode. - echo Free models: GPT-5 Nano, Grok Code, GLM-4.7, etc. - echo You can also authenticate with Qwen for additional models. - ) + echo To start NomadArch, run: + echo Launch-Windows.bat + echo. + echo Available Free Models: + echo - GPT-5 Nano (fast) + echo - Grok Code (coding) + echo - GLM-4.7 (general) + echo - Doubao (creative) + echo - Big Pickle (experimental) + echo. + echo [%date% %time%] Installation SUCCESSFUL >> "%LOG_FILE%" ) echo.