diff --git a/artifact_comfyui_download.sh b/artifact_comfyui_download.sh new file mode 100755 index 0000000..37961b9 --- /dev/null +++ b/artifact_comfyui_download.sh @@ -0,0 +1,484 @@ +#!/bin/bash +# +# ComfyUI Model Downloader - A Beautiful CLI Tool +# Downloads AI models from HuggingFace with style and grace +# +# Usage: ./artifact_comfyui_download.sh [options] +# + +set -euo pipefail + +# ============================================================================ +# COLOR PALETTE - Beautiful Terminal Colors +# ============================================================================ + +# Reset +RESET='\033[0m' + +# Foreground Colors +BLACK='\033[0;30m' +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +BLUE='\033[0;34m' +MAGENTA='\033[0;35m' +CYAN='\033[0;36m' +WHITE='\033[0;37m' + +# Bold +BOLD_BLACK='\033[1;30m' +BOLD_RED='\033[1;31m' +BOLD_GREEN='\033[1;32m' +BOLD_YELLOW='\033[1;33m' +BOLD_BLUE='\033[1;34m' +BOLD_MAGENTA='\033[1;35m' +BOLD_CYAN='\033[1;36m' +BOLD_WHITE='\033[1;37m' + +# Background Colors +BG_BLACK='\033[40m' +BG_RED='\033[41m' +BG_GREEN='\033[42m' +BG_YELLOW='\033[43m' +BG_BLUE='\033[44m' +BG_MAGENTA='\033[45m' +BG_CYAN='\033[46m' +BG_WHITE='\033[47m' + +# Styles +DIM='\033[2m' +ITALIC='\033[3m' +UNDERLINE='\033[4m' +BLINK='\033[5m' +REVERSE='\033[7m' + +# ============================================================================ +# UNICODE CHARACTERS - Make it Pretty +# ============================================================================ + +CHECK_MARK="โœ“" +CROSS_MARK="โœ—" +ROCKET="๐Ÿš€" +PACKAGE="๐Ÿ“ฆ" +DOWNLOAD="โฌ‡๏ธ" +SPARKLES="โœจ" +FIRE="๐Ÿ”ฅ" +CLOCK="โฑ๏ธ" +FOLDER="๐Ÿ“" +LINK="๐Ÿ”—" +STAR="โญ" +WARNING="โš ๏ธ" +INFO="โ„น๏ธ" +ARROW_RIGHT="โ†’" +DOUBLE_ARROW="ยป" +BOX_LIGHT="โ”€" +BOX_HEAVY="โ”" +BOX_DOUBLE="โ•" + +# ============================================================================ +# CONFIGURATION +# ============================================================================ + +# Script directory +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +# Default configuration file path +# Try multiple possible locations +if [[ -f "${HOME}/Projects/runpod/comfyui_models.yaml" ]]; then + CONFIG_FILE="${HOME}/Projects/runpod/comfyui_models.yaml" +elif [[ -f "${PROJECT_ROOT}/comfyui_models.yaml" ]]; then + CONFIG_FILE="${PROJECT_ROOT}/comfyui_models.yaml" +elif [[ -f "${SCRIPT_DIR}/comfyui_models.yaml" ]]; then + CONFIG_FILE="${SCRIPT_DIR}/comfyui_models.yaml" +else + CONFIG_FILE="" # No config file by default +fi + +# Default cache directory (use HuggingFace default) +CACHE_DIR="${CACHE_DIR:-${HOME}/.cache/huggingface}" + +# HuggingFace token from environment or .env file +if [[ -f "${PROJECT_ROOT}/.env" ]]; then + HF_TOKEN=$(grep ^HF_TOKEN "${PROJECT_ROOT}/.env" | cut -d'=' -f2- | tr -d '"' | tr -d "'" || true) +fi +HF_TOKEN="${HF_TOKEN:-}" + +# ============================================================================ +# UTILITY FUNCTIONS - The Magic Happens Here +# ============================================================================ + +# Print functions with beautiful formatting +print_banner() { + local text="$1" + local width=80 + local padding=$(( (width - ${#text} - 2) / 2 )) + + echo -e "" + echo -e "${BOLD_CYAN}${BOX_DOUBLE}$(printf '%.0s'"${BOX_DOUBLE}" $(seq 1 $width))${BOX_DOUBLE}${RESET}" + echo -e "${BOLD_CYAN}${BOX_DOUBLE}$(printf '%.0s ' $(seq 1 $padding))${BOLD_MAGENTA}${text}$(printf '%.0s ' $(seq 1 $padding))${BOLD_CYAN}${BOX_DOUBLE}${RESET}" + echo -e "${BOLD_CYAN}${BOX_DOUBLE}$(printf '%.0s'"${BOX_DOUBLE}" $(seq 1 $width))${BOX_DOUBLE}${RESET}" + echo -e "" +} + +print_section() { + local text="$1" + echo -e "\n${BOLD_YELLOW}${DOUBLE_ARROW} ${text}${RESET}" + echo -e "${CYAN}$(printf '%.0s'"${BOX_LIGHT}" $(seq 1 80))${RESET}" +} + +print_success() { + echo -e "${BOLD_GREEN}${CHECK_MARK} $1${RESET}" +} + +print_error() { + echo -e "${BOLD_RED}${CROSS_MARK} $1${RESET}" >&2 +} + +print_warning() { + echo -e "${BOLD_YELLOW}${WARNING} $1${RESET}" +} + +print_info() { + echo -e "${BOLD_CYAN}${INFO} $1${RESET}" +} + +print_step() { + local current="$1" + local total="$2" + local text="$3" + echo -e "${BOLD_BLUE}[${current}/${total}]${RESET} ${MAGENTA}${DOWNLOAD}${RESET} ${text}" +} + +print_detail() { + echo -e " ${DIM}${CYAN}${ARROW_RIGHT} $1${RESET}" +} + +# Progress bar function +show_progress() { + local current="$1" + local total="$2" + local width=50 + local percentage=$((current * 100 / total)) + local filled=$((current * width / total)) + local empty=$((width - filled)) + + printf "\r ${BOLD_CYAN}Progress: ${RESET}[" + printf "${BG_GREEN}${BOLD_WHITE}%${filled}s${RESET}" | tr ' ' 'โ–ˆ' + printf "${DIM}%${empty}s${RESET}" | tr ' ' 'โ–‘' + printf "] ${BOLD_YELLOW}%3d%%${RESET} ${DIM}(%d/%d)${RESET}" "$percentage" "$current" "$total" +} + +# Parse YAML (simple implementation) +parse_yaml() { + local yaml_file="$1" + local category="$2" + + python3 - < /dev/null; then + missing_deps+=("python3") + fi + + # Check pip + if ! command -v pip3 &> /dev/null; then + missing_deps+=("pip3") + fi + + # Check required Python packages + if ! python3 -c "import yaml" 2>/dev/null; then + print_warning "PyYAML not installed, installing..." + pip3 install pyyaml -q + fi + + if ! python3 -c "import huggingface_hub" 2>/dev/null; then + print_warning "huggingface_hub not installed, installing..." + pip3 install huggingface_hub -q + fi + + if [[ ${#missing_deps[@]} -gt 0 ]]; then + print_error "Missing dependencies: ${missing_deps[*]}" + exit 1 + fi + + print_success "All dependencies satisfied" +} + +# Validate configuration +validate_config() { + print_section "Validating Configuration" + + if [[ -n "$CONFIG_FILE" ]]; then + if [[ ! -f "$CONFIG_FILE" ]]; then + print_error "Configuration file not found: $CONFIG_FILE" + exit 1 + fi + print_success "Configuration file found: ${CYAN}${CONFIG_FILE}${RESET}" + else + print_warning "No configuration file specified" + fi + + if [[ -z "$HF_TOKEN" ]]; then + print_error "HF_TOKEN not set. Please set it in .env file or environment." + exit 1 + fi + print_success "HuggingFace token configured: ${DIM}${HF_TOKEN:0:10}...${RESET}" + + if [[ ! -d "$CACHE_DIR" ]]; then + print_info "Creating cache directory: ${CYAN}${CACHE_DIR}${RESET}" + mkdir -p "$CACHE_DIR" + fi + print_success "Cache directory ready: ${CYAN}${CACHE_DIR}${RESET}" +} + +# Download a single model +download_model() { + local repo_id="$1" + local description="$2" + local size_gb="$3" + + print_detail "Repository: ${BOLD_WHITE}${repo_id}${RESET}" + print_detail "Description: ${description}" + print_detail "Size: ${BOLD_YELLOW}${size_gb}GB${RESET}" + + # Download using Python + python3 - <