diff --git a/bin/functions/Toolbox/Troubleshooting/remove_node_modules.bat b/bin/functions/Toolbox/Troubleshooting/remove_node_modules.bat index 7e491c0..566da02 100644 --- a/bin/functions/Toolbox/Troubleshooting/remove_node_modules.bat +++ b/bin/functions/Toolbox/Troubleshooting/remove_node_modules.bat @@ -4,7 +4,6 @@ cd /d "%st_install_path%" echo %blue_bg%[%time%]%reset% %blue_fg_strong%[INFO]%reset% Removing node_modules folder... rmdir /s /q "node_modules" -call npm cache clean --force echo %blue_bg%[%time%]%reset% %blue_fg_strong%[INFO]%reset% node_modules successfully removed. pause diff --git a/install.sh b/install.sh index 52cbf79..3faae96 100755 --- a/install.sh +++ b/install.sh @@ -121,12 +121,6 @@ install_miniconda() { echo "Miniconda installed successfully in $HOME/miniconda" } -# Define the paths and filenames for the shortcut creation -script_path="$(realpath "$(dirname "$0")")/launcher.sh" -icon_path="$(realpath "$(dirname "$0")")/st-launcher.ico" -script_name=st-launcher -desktop_dir="$(eval echo ~$(logname))/Desktop" -desktop_file="$desktop_dir/st-launcher.desktop" # Function to log messages with timestamps and colors log_message() { @@ -231,77 +225,73 @@ install_git() { } -# Function to install Node.js and npm -install_nodejs_npm() { - if ! command -v npm &>/dev/null || ! command -v node &>/dev/null; then - echo -e "${yellow_fg_strong}[WARN] Node.js and/or npm are not installed on this system.${reset}" +install_nodejs() { + if ! command -v node &> /dev/null; then + log_message "WARN" "${yellow_fg_strong}Node.js is not installed on this system${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Installing Node.js and npm using apt..." - sudo apt-get update - sudo apt-get install -y curl - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - source "$NVM_DIR/nvm.sh" - read -p "Press Enter to continue..." - nvm install --lts - nvm use --lts - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Installing Node.js and npm using yum..." - sudo yum install -y curl - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - source "$NVM_DIR/nvm.sh" - read -p "Press Enter to continue..." - nvm install --lts - nvm use --lts - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Installing Node.js and npm using apk..." - sudo apk add curl - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - source "$NVM_DIR/nvm.sh" - read -p "Press Enter to continue..." - nvm install --lts - nvm use --lts - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Installing Node.js and npm using pacman..." - sudo pacman -S --noconfirm curl - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - source "$NVM_DIR/nvm.sh" - read -p "Press Enter to continue..." - nvm install --lts - nvm use --lts - elif command -v emerge &>/dev/null; then - # Gentoo-based system - log_message "INFO" "Installing Node.js and npm using emerge..." - sudo emerge -av net-misc/curl - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash - source "$NVM_DIR/nvm.sh" - read -p "Press Enter to continue..." - nvm install --lts - nvm use --lts - elif command -v pkg &>/dev/null; then - # Termux on Android - log_message "INFO" "Installing Node.js and npm using pkg..." - pkg install nodejs npm - elif command -v brew &>/dev/null; then - # macOS - log_message "INFO" "Installing Node.js and npm using Homebrew..." - brew install node - elif command -v zypper &>/dev/null; then - # openSUSE - log_message "INFO" "Installing Node.js and npm using zypper..." - sudo zypper --non-interactive install nodejs npm - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 - fi + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + log_message "INFO" "Detected apt (Debian/Ubuntu). Installing Node.js..." + sudo apt update && sudo apt install -y nodejs npm + ;; + dnf|yum) + log_message "INFO" "Detected dnf/yum (Red Hat/Fedora). Installing Node.js..." + sudo $package_manager install -y nodejs npm + ;; + apk) + log_message "INFO" "Detected apk (Alpine). Installing Node.js..." + sudo apk add nodejs npm + ;; + pacman) + log_message "INFO" "Detected pacman (Arch). Installing Node.js..." + sudo pacman -Sy --noconfirm nodejs npm + ;; + emerge) + log_message "INFO" "Detected emerge (Gentoo). Installing Node.js..." + sudo emerge --ask nodejs npm + ;; + zypper) + log_message "INFO" "Detected zypper (openSUSE). Installing Node.js..." + sudo zypper install -y nodejs npm + ;; + xbps) + log_message "INFO" "Detected xbps (Void). Installing Node.js..." + sudo xbps-install -y nodejs npm + ;; + nix) + log_message "INFO" "Detected nix (NixOS). Installing Node.js..." + nix-env -iA nixpkgs.nodejs + ;; + guix) + log_message "INFO" "Detected guix (Guix). Installing Node.js..." + guix package -i node + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + exit 1 + ;; + esac + ;; + Darwin) + log_message "INFO" "Detected macOS. Installing Node.js via Homebrew..." + if ! command -v brew &> /dev/null; then + log_message "ERROR" "${red_fg_strong}Homebrew not installed. Install it first: https://brew.sh/${reset}" + exit 1 + fi + brew install node + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + exit 1 + ;; + esac - echo "${green_fg_strong}Node.js and npm installed and configured with nvm.${reset}" + log_message "INFO" "${green_fg_strong}Node.js is installed.${reset}" else - echo -e "${blue_fg_strong}[INFO] Node.js and npm are already installed.${reset}" + log_message "INFO" "${blue_fg_strong}Node.js is already installed.${reset}" fi } @@ -552,6 +542,103 @@ install_all_final() { } + + + + + + + +######################################################################################## +######################################################################################## +####################### SUPPORT MENU FUNCTIONS ######################################## +######################################################################################## +######################################################################################## + +# Functions for Support Menu - Backend +issue_report() { + if [ "$EUID" -eq 0 ]; then + log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" + else + if [ "$(uname -s)" == "Darwin" ]; then + open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose + else + xdg-open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose + fi + fi + read -p "Press Enter to continue..." + support +} + +documentation() { + if [ "$EUID" -eq 0 ]; then + log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" + else + if [ "$(uname -s)" == "Darwin" ]; then + open https://docs.sillytavern.app/ + else + xdg-open https://docs.sillytavern.app/ + fi + fi + read -p "Press Enter to continue..." + support +} + +discord() { + if [ "$EUID" -eq 0 ]; then + log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" + else + if [ "$(uname -s)" == "Darwin" ]; then + open https://discord.gg/sillytavern + else + xdg-open https://discord.gg/sillytavern + fi + fi + read -p "Press Enter to continue..." + support +} + + +############################################################ +################# SUPPORT MENU - FRONTEND ################## +############################################################ +support() { + echo -e "\033]0;SillyTavern [SUPPORT]\007" + clear + echo -e "${blue_fg_strong}| > / Installer / Support |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. I want to report an issue" + echo " 2. Documentation" + echo " 3. Discord" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " support_choice + + # Support Menu - Backend + case $support_choice in + 1) issue_report ;; + 2) documentation ;; + 3) discord ;; + 0) installer ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + support ;; + esac +} + +######################################################################################## +######################################################################################## +####################### INSTALLER MENU FUNCTIONS ###################################### +######################################################################################## +######################################################################################## + + + # Function to install SillyTavern install_sillytavern() { echo -e "\033]0;SillyTavern [INSTALL-ST]\007" @@ -564,24 +651,10 @@ install_sillytavern() { git clone https://github.com/SillyTavern/SillyTavern.git log_message "INFO" "${green_fg_strong}SillyTavern installed successfully.${reset}" - # Ask if the user wants to create a desktop shortcut - read -p "Do you want to create a shortcut on the desktop? [Y/n] " create_shortcut - if [[ "${create_shortcut}" == "Y" || "${create_shortcut}" == "y" ]]; then - - # Create the desktop shortcut - echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Creating desktop shortcut..." - - echo "[Desktop Entry]" > "$desktop_file" - echo "Version=1.0" >> "$desktop_file" - echo "Type=Application" >> "$desktop_file" - echo "Name=$script_name" >> "$desktop_file" - echo "Exec=$script_path" >> "$desktop_file" - echo "Icon=$icon_path" >> "$desktop_file" - echo "Terminal=true" >> "$desktop_file" - echo "Comment=SillyTavern Launcher" >> "$desktop_file" - chmod +x "$desktop_file" - - echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} ${green_fg_strong}Desktop shortcut created at: $desktop_file${reset}" + # Ask if the user wants to create desktop shortcuts + read -p "Do you want to create desktop shortcuts? [Y/n] " create_shortcut + if [[ "${create_shortcut}" =~ ^[Yy]$ ]]; then + create_desktop_shortcuts fi # Ask if the user wants to start the launcher @@ -597,6 +670,102 @@ install_sillytavern() { } +create_desktop_shortcuts() { + # Common variables + stl_root="$(dirname "$(realpath "$0")")" + st_install_path="$stl_root/SillyTavern" + desktop_dir="" + launcher_script="$stl_root/launcher.sh" + sillytavern_script="$st_install_path/start.sh" + icon_launcher="$stl_root/st-launcher.ico" + icon_sillytavern="$stl_root/st.ico" + + # Detect desktop environment + case "$(uname -s)" in + Linux) + desktop_dir="$HOME/Desktop" + # Create directory if it doesn't exist + mkdir -p "$desktop_dir" + + # Create launcher shortcut + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Creating ST-Launcher shortcut..." + cat << EOF > "$desktop_dir/ST-Launcher.desktop" +[Desktop Entry] +Version=1.0 +Type=Application +Name=SillyTavern Launcher +Exec="$launcher_script" +Icon=$icon_launcher +Terminal=true +Comment=Launch SillyTavern AI Interface +Path=$stl_root +EOF + chmod +x "$desktop_dir/ST-Launcher.desktop" + + # Create SillyTavern direct start shortcut + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Creating SillyTavern shortcut..." + cat << EOF > "$desktop_dir/SillyTavern.desktop" +[Desktop Entry] +Version=1.0 +Type=Application +Name=SillyTavern +Exec="$sillytavern_script" +Icon=$icon_sillytavern +Terminal=true +Comment=Start SillyTavern Directly +Path=$st_install_path +EOF + chmod +x "$desktop_dir/SillyTavern.desktop" + ;; + + Darwin) + desktop_dir="$HOME/Desktop" + # Create launcher shortcut + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Creating ST-Launcher shortcut..." + cat << EOF > "$desktop_dir/ST-Launcher.command" +#!/bin/zsh +cd "$stl_root" && ./launcher.sh +EOF + chmod +x "$desktop_dir/ST-Launcher.command" + + # Create SillyTavern direct start shortcut + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Creating SillyTavern shortcut..." + cat << EOF > "$desktop_dir/SillyTavern.command" +#!/bin/zsh +cd "$st_install_path" && ./start.sh +EOF + chmod +x "$desktop_dir/SillyTavern.command" + + # Set custom icons (requires osascript) + if [ -f "$icon_launcher" ]; then + osascript << EOF +set iconPath to POSIX file "$icon_launcher" +tell application "Finder" to set label icon of alias file ("$desktop_dir/ST-Launcher.command" as POSIX file) to iconPath +EOF + fi + + if [ -f "$icon_sillytavern" ]; then + osascript << EOF +set iconPath to POSIX file "$icon_sillytavern" +tell application "Finder" to set label icon of alias file ("$desktop_dir/SillyTavern.command" as POSIX file) to iconPath +EOF + fi + ;; + + *) + echo -e "${red_fg_strong}Unsupported operating system for desktop shortcuts${reset}" + return 1 + ;; + esac + + # Verify creation + if [ -f "$desktop_dir/ST-Launcher"* ] && [ -f "$desktop_dir/SillyTavern"* ]; then + echo -e "${green_fg_strong}Shortcuts created successfully on "$desktop_dir/SillyTavern" ${reset}" + else + echo -e "${yellow_fg_strong}Warning: Shortcuts might not have been created correctly${reset}" + fi +} + # Function to install Extras install_extras() { echo -e "\033]0;SillyTavern [INSTALL-EXTRAS]\007" @@ -788,23 +957,35 @@ install_xtts_successful() { } +# Exit Function +exit_program() { + clear + echo "Bye!" + exit 0 +} + ############################################################ ################# INSTALLER - FRONTEND ##################### ############################################################ installer() { echo -e "\033]0;SillyTavern [INSTALLER]\007" clear - echo -e "${blue_fg_strong}/ Installer${reset}" - echo "-------------------------------------" - echo "What would you like to do?" - echo "1. Install SillyTavern" - echo "2. Install Extras" - echo "3. Install XTTS" - echo "4. Install All Options From Above" - echo "5. Support" - echo "0. Exit" - - read -p "Choose Your Destiny (default is 1): " choice + echo -e "${blue_fg_strong}| > / Installer |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Install SillyTavern" + echo " 2. Install XTTS" + echo " 3. Support" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Discontinued |${reset}" + echo " 4. Install Extras" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Exit" + echo -e "${cyan_fg_strong} _____________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny (default is 1): " choice # Default to choice 1 if no input is provided if [ -z "$choice" ]; then @@ -814,152 +995,164 @@ installer() { ################# INSTALLER - BACKEND ##################### case $choice in 1) install_sillytavern ;; - 2) install_extras ;; - 3) install_xtts ;; - 4) install_all ;; - 5) support ;; - 0) exit ;; + 2) install_xtts ;; + 3) support ;; + 4) install_extras ;; +# 4) install_all ;; + 0) exit_program ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." installer ;; esac } -# Functions for Support Menu - Backend -issue_report() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose - else - xdg-open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose - fi - fi - read -p "Press Enter to continue..." - support -} -documentation() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://docs.sillytavern.app/ - else - xdg-open https://docs.sillytavern.app/ - fi - fi - read -p "Press Enter to continue..." - support -} +detect_package_manager() { + local package_manager -discord() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://discord.gg/sillytavern + # Check for macOS first + if [ "$(uname)" = "Darwin" ]; then + if command -v brew &> /dev/null; then + echo "brew" + return 0 else - xdg-open https://discord.gg/sillytavern + echo "unknown" + return 1 fi fi - read -p "Press Enter to continue..." - support + + # Check for Linux package managers + case "$(true; command -v apt dnf yum apk pacman emerge zypper xbps-install guix nix-env 2>/dev/null | head -n1)" in + *apt) package_manager="apt" ;; + *dnf) package_manager="dnf" ;; + *yum) package_manager="yum" ;; + *apk) package_manager="apk" ;; + *pacman) package_manager="pacman" ;; + *emerge) package_manager="emerge" ;; + *zypper) package_manager="zypper" ;; + *xbps-install) package_manager="xbps" ;; + *guix) package_manager="guix" ;; + *nix-env) package_manager="nix" ;; + *) + if [ -f /etc/os-release ]; then + os_id=$(grep -E '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"') + case "$os_id" in + almalinux|centos_stream|ol|rhel|rocky|fedora|fedoraremixforwsl|nobara) + package_manager="yum" ;; + alpine|wolfi) + package_manager="apk" ;; + arch|arch32|archcraft|arcolinux|arkane|artix|aurora|bazzite|blackarch|blendos|bluefin|bodhi|cachyos|chimera|chimeraos|endeavouros|garuda|hyperbola|kaos|manjaro|manjaro-arm|rebornos|steamos|void) + package_manager="pacman" ;; + debian|devuan|elementary|kali|linuxmint|parrot|pika|pisilinux|pop|pureos|raspbian|tails|ubuntu|ubuntu_kylin|vanillaos|zorin) + package_manager="apt" ;; + opensuse-leap|opensuse-tumbleweed|sled|sles) + package_manager="zypper" ;; + gentoo|funtoo) + package_manager="emerge" ;; + nixos) + package_manager="nix" ;; + guix) + package_manager="guix" ;; + clear-linux-os|miraclelinux|photon|solus|tencentos|tinycore|trisquel|ultramarine) + package_manager="unknown" ;; # Custom handling needed + *) + package_manager="unknown" ;; + esac + else + package_manager="unknown" + fi + ;; + esac + + echo "$package_manager" } -# Support Menu - Frontend -support() { - echo -e "\033]0;SillyTavern [SUPPORT]\007" - clear - echo -e "${blue_fg_strong}/ Home / Support${reset}" - echo "-------------------------------------" - echo "What would you like to do?" - echo "1. I want to report an issue" - echo "2. Documentation" - echo "3. Discord" - echo "0. Back to installer" +# Main function to install dependencies based on package manager +install_dependencies() { + PACKAGE_MANAGER=$(detect_package_manager) - read -p "Choose Your Destiny: " support_choice - - # Support Menu - Backend - case $support_choice in - 1) issue_report ;; - 2) documentation ;; - 3) discord ;; - 0) installer ;; - *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" - read -p "Press Enter to continue..." - support ;; + case "$PACKAGE_MANAGER" in + apt) + log_message "INFO" "Detected APT on Debian/Ubuntu-based system." + sudo apt update -y + install_git + install_nodejs + install_miniconda + installer + ;; + dnf|yum) + log_message "INFO" "Detected DNF/YUM on RHEL-based system." + sudo $PACKAGE_MANAGER install -y epel-release + install_git + install_nodejs + install_miniconda + installer + ;; + pacman) + log_message "INFO" "Detected Pacman on Arch-based system." + sudo pacman -Sy --noconfirm + install_git + install_nodejs + install_miniconda + installer + ;; + apk) + log_message "INFO" "Detected APK on Alpine Linux." + sudo apk update + install_git + install_nodejs + install_miniconda + installer + ;; + zypper) + log_message "INFO" "Detected Zypper on openSUSE." + sudo zypper refresh + install_git + install_nodejs + install_miniconda + installer + ;; + emerge) + log_message "INFO" "Detected Portage on Gentoo." + sudo emerge --sync + install_git + install_nodejs + install_miniconda + installer + ;; + nix) + log_message "INFO" "Detected Nix Package Manager." + nix-env -iA nixpkgs.git nixpkgs.nodejs + install_miniconda + installer + ;; + guix) + log_message "INFO" "Detected Guix Package Manager." + install_git + install_nodejs + install_miniconda + installer + ;; + brew) + log_message "INFO" "Detected Homebrew on macOS." + if ! command -v brew &> /dev/null; then + log_message "ERROR" "Homebrew is not installed. Please install it first: https://brew.sh/" + exit 1 + fi + install_git + install_nodejs + install_miniconda + installer + ;; + *) + log_message "ERROR" "Unknown package manager. Please install dependencies manually." + exit 1 + ;; esac } -# Check if the script is running on macOS -if [ "$(uname)" == "Darwin" ]; then - IS_MACOS="1" -fi - -# Detect the package manager and execute the appropriate installation -if [ -n "$IS_MACOS" ]; then - log_message "INFO" "${blue_fg_strong}Detected macOS system.${reset}" - # macOS - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v apt-get &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected Debian/Ubuntu-based system.${reset}" - # Debian/Ubuntu - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v yum &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected Red Hat/Fedora-based system.${reset}" - # Red Hat/Fedora - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v apk &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected Alpine Linux-based system.${reset}" - # Alpine Linux - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v pacman &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected Arch Linux-based system.${reset}" - # Arch Linux - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v emerge &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected Gentoo Linux-based system. Now you are the real CHAD${reset}" - # Gentoo Linux - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v pkg &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected pkg System${reset}" - # pkg - install_git - install_nodejs_npm - install_miniconda - installer -elif command -v zypper &>/dev/null; then - log_message "INFO" "${blue_fg_strong}Detected openSUSE system.${reset}" - # openSUSE - install_git - install_nodejs_npm - install_miniconda - installer -else - log_message "ERROR" "${red_fg_strong}Unsupported package manager. Cannot detect Linux distribution.${reset}" - exit 1 -fi - - +# Startup functions +detect_package_manager +install_dependencies +installer \ No newline at end of file diff --git a/launcher.sh b/launcher.sh index 6c90ff6..64cd95a 100755 --- a/launcher.sh +++ b/launcher.sh @@ -23,7 +23,7 @@ # Note: Modify the script as needed to fit your requirements. # ---------------------------------------------------------- -echo -e "\033]0;SillyTavern Launcher\007" +echo -e "\033]0;STL\007" # ANSI Escape Code for Colors reset="\033[0m" @@ -40,30 +40,189 @@ red_bg="\033[41m" blue_bg="\033[44m" yellow_bg="\033[43m" -# Environment Variables (TOOLBOX 7-Zip) -zip7version="7z2301-x64" -zip7_install_path="/usr/local/bin" - -# Environment Variables (TOOLBOX FFmpeg) -ffmpeg_url="https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z" -ffdownload_path="/tmp/ffmpeg.7z" -ffextract_path="/opt/ffmpeg" -bin_path="$ffextract_path/bin" - -# Environment Variables (TOOLBOX Node.js) -node_installer_path="/tmp/NodejsInstaller.sh" - -# Environment Variables (TOOLBOX Install Extras) +# Environment Variables (miniconda3) miniconda_path="$HOME/miniconda3" +miniconda_path_mingw="$miniconda_path/Library/mingw-w64/bin" +miniconda_path_usrbin="$miniconda_path/Library/usr/bin" +miniconda_path_bin="$miniconda_path/Library/bin" +miniconda_path_scripts="$miniconda_path/Scripts" -# Define variables to track module status -modules_path="$HOME/modules.txt" -coqui_trigger="false" -rvc_trigger="false" -talkinghead_trigger="false" -caption_trigger="false" -summarize_trigger="false" -edge_tts_trigger="false" +# Environment Variables (FFmpeg) +ffmpeg_download_url="https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7z" +ffmpeg_download_path="$(dirname "$0")/bin/ffmpeg.7z" +ffmpeg_install_path="/opt/ffmpeg" +ffmpeg_path_bin="$ffmpeg_install_path/bin" + +# Define variables to track module status (EXTRAS) +export extras_modules_path="$(dirname "$0")/bin/settings/modules-extras.txt" +export cuda_trigger="false" +export rvc_trigger="false" +export talkinghead_trigger="false" +export caption_trigger="false" +export summarize_trigger="false" +export listen_trigger="false" +export whisper_trigger="false" +export edge_tts_trigger="false" +export websearch_trigger="false" +if [ -f "$extras_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$extras_modules_path" +fi + +# Define variables to track module status (XTTS) +export xtts_modules_path="$(dirname "$0")/bin/settings/modules-xtts.txt" +export xtts_cuda_trigger="false" +export xtts_hs_trigger="false" +export xtts_deepspeed_trigger="false" +export xtts_cache_trigger="false" +export xtts_listen_trigger="false" +export xtts_model_trigger="false" +if [ -f "$xtts_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$xtts_modules_path" +fi + +# Define variables to track module status (STABLE DIFFUSION WEBUI) +export sdwebui_modules_path="$(dirname "$0")/bin/settings/modules-sdwebui.txt" +export sdwebui_autolaunch_trigger="false" +export sdwebui_api_trigger="false" +export sdwebui_listen_trigger="false" +export sdwebui_port_trigger="false" +export sdwebui_optsdpattention_trigger="false" +export sdwebui_themedark_trigger="false" +export sdwebui_skiptorchcudatest_trigger="false" +export sdwebui_lowvram_trigger="false" +export sdwebui_medvram_trigger="false" +if [ -f "$sdwebui_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$sdwebui_modules_path" +fi + +# Define variables to track module status (STABLE DIFFUSION WEBUI FORGE) +export sdwebuiforge_modules_path="$(dirname "$0")/bin/settings/modules-sdwebuiforge.txt" +export sdwebuiforge_autolaunch_trigger="false" +export sdwebuiforge_api_trigger="false" +export sdwebuiforge_listen_trigger="false" +export sdwebuiforge_port_trigger="false" +export sdwebuiforge_optsdpattention_trigger="false" +export sdwebuiforge_themedark_trigger="false" +export sdwebuiforge_skiptorchcudatest_trigger="false" +export sdwebuiforge_lowvram_trigger="false" +export sdwebuiforge_medvram_trigger="false" +if [ -f "$sdwebuiforge_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$sdwebuiforge_modules_path" +fi + +# Define variables to track module status (TEXT GENERATION WEBUI OOBABOOGA) +export ooba_modules_path="$(dirname "$0")/bin/settings/modules-ooba.txt" +export ooba_autolaunch_trigger="false" +export ooba_extopenai_trigger="false" +export ooba_listen_trigger="false" +export ooba_listenport_trigger="false" +export ooba_apiport_trigger="false" +export ooba_verbose_trigger="false" +if [ -f "$ooba_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$ooba_modules_path" +fi + +# Define variables to track module status (TABBYAPI) +export tabbyapi_modules_path="$(dirname "$0")/bin/settings/modules-tabbyapi.txt" +export tabbyapi_selectedmodelname_trigger="false" +export selected_tabbyapi_model_folder="" + +export tabbyapi_ignoreupdate_trigger="false" +export tabbyapi_port_trigger="false" +export tabbyapi_port="" +export tabbyapi_host_trigger="false" +export tabbyapi_maxseqlen_trigger="false" +export tabbyapi_maxseqlen="" +export tabbyapi_ropealpha_trigger="" +export tabbyapi_ropealpha="" +export ttabbyapi_cachemode_trigger="" +export tabbyapi_cachemode="" +export ttabbyapi_updatedeps_trigger="" +if [ -f "$tabbyapi_modules_path" ]; then + while IFS='=' read -r key value; do + export "$key"="$value" + done < "$tabbyapi_modules_path" +fi + +# Define variables for install locations (Core Utilities) +stl_root="$(dirname "$(realpath "$0")")" +st_install_path="$stl_root/SillyTavern" +st_package_json_path="$st_install_path/package.json" +extras_install_path="$stl_root/SillyTavern-extras" +st_backup_path="$stl_root/SillyTavern-backups" +NODE_ENV="production" + +# Define variables for install locations (Image Generation) +image_generation_dir="$stl_root/image-generation" +sdwebui_install_path="$image_generation_dir/stable-diffusion-webui" +sdwebuiforge_install_path="$image_generation_dir/stable-diffusion-webui-forge" +comfyui_install_path="$image_generation_dir/ComfyUI" +fooocus_install_path="$image_generation_dir/Fooocus" +invokeai_install_path="$image_generation_dir/InvokeAI" +ostrisaitoolkit_install_path="$image_generation_dir/ai-toolkit" + +# Define variables for install locations (Text Completion) +text_completion_dir="$stl_root/text-completion" +ooba_install_path="$text_completion_dir/text-generation-webui" +koboldcpp_install_path="$text_completion_dir/dev-koboldcpp" +llamacpp_install_path="$text_completion_dir/dev-llamacpp" +tabbyapi_install_path="$text_completion_dir/tabbyAPI" + +# Define variables for install locations (Voice Generation) +voice_generation_dir="$stl_root/voice-generation" +alltalk_install_path="$voice_generation_dir/alltalk_tts" +alltalk_v2_install_path="$voice_generation_dir/alltalk_tts" +xtts_install_path="$voice_generation_dir/xtts" +rvc_install_path="$voice_generation_dir/Retrieval-based-Voice-Conversion-WebUI" + +# Define variables for the core directories +bin_dir="$stl_root/bin" +log_dir="$bin_dir/logs" +functions_dir="$bin_dir/functions" + +# Define variables for the directories for Toolbox +toolbox_dir="$functions_dir/Toolbox" +troubleshooting_dir="$toolbox_dir/Troubleshooting" +backup_dir="$toolbox_dir/Backup" + +# Define variables for the directories for App Installer +app_installer_image_generation_dir="$functions_dir/Toolbox/App_Installer/Image_Generation" +app_installer_text_completion_dir="$functions_dir/Toolbox/App_Installer/Text_Completion" +app_installer_voice_generation_dir="$functions_dir/Toolbox/App_Installer/Voice_Generation" +app_installer_core_utilities_dir="$functions_dir/Toolbox/App_Installer/Core_Utilities" + +# Define variables for the directories for App Uninstaller +app_uninstaller_image_generation_dir="$functions_dir/Toolbox/App_Uninstaller/Image_Generation" +app_uninstaller_text_completion_dir="$functions_dir/Toolbox/App_Uninstaller/Text_Completion" +app_uninstaller_voice_generation_dir="$functions_dir/Toolbox/App_Uninstaller/Voice_Generation" +app_uninstaller_core_utilities_dir="$functions_dir/Toolbox/App_Uninstaller/Core_Utilities" + +# Define variables for the directories for App Launcher +app_launcher_image_generation_dir="$functions_dir/Toolbox/App_Launcher/Image_Generation" +app_launcher_text_completion_dir="$functions_dir/Toolbox/App_Launcher/Text_Completion" +app_launcher_voice_generation_dir="$functions_dir/Toolbox/App_Launcher/Voice_Generation" +app_launcher_core_utilities_dir="$functions_dir/Toolbox/App_Launcher/Core_Utilities" + +# Define variables for the directories for Editor +editor_image_generation_dir="$functions_dir/Toolbox/Editor/Image_Generation" +editor_text_completion_dir="$functions_dir/Toolbox/Editor/Text_Completion" +editor_voice_generation_dir="$functions_dir/Toolbox/Editor/Voice_Generation" +editor_core_utilities_dir="$functions_dir/Toolbox/Editor/Core_Utilities" + +# Define variables for logging +st_auto_repair="$log_dir/autorepair-setting.txt" +logs_stl_console_path="$log_dir/stl.log" +logs_st_console_path="$log_dir/st_console_output.log" # Function to log messages with timestamps and colors @@ -95,108 +254,83 @@ log_message() { #log_message "DEBUG" "This is a debug message." #read -p "Press Enter to continue..." + + + # Function to install Git install_git() { if ! command -v git &> /dev/null; then log_message "WARN" "${yellow_fg_strong}Git is not installed on this system${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Installing Git using apt..." - sudo apt-get update - sudo apt-get install -y git - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Installing Git using yum..." - sudo yum install -y git - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Installing Git using apk..." - sudo apk add git - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Installing Git using pacman..." - sudo pacman -S --noconfirm git - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Installing Git using emerge..." - sudo emerge --ask dev-vcs/git - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 - fi + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + log_message "INFO" "Detected apt (Debian/Ubuntu). Installing Git..." + sudo apt update && sudo apt install -y git + ;; + dnf|yum) + log_message "INFO" "Detected dnf/yum (Red Hat/Fedora). Installing Git..." + sudo $package_manager install -y git + ;; + apk) + log_message "INFO" "Detected apk (Alpine). Installing Git..." + sudo apk add git + ;; + pacman) + log_message "INFO" "Detected pacman (Arch). Installing Git..." + sudo pacman -Sy --noconfirm git + ;; + emerge) + log_message "INFO" "Detected emerge (Gentoo). Installing Git..." + sudo emerge --ask dev-vcs/git + ;; + zypper) + log_message "INFO" "Detected zypper (openSUSE). Installing Git..." + sudo zypper install -y git + ;; + xbps) + log_message "INFO" "Detected xbps (Void). Installing Git..." + sudo xbps-install -y git + ;; + nix) + log_message "INFO" "Detected nix (NixOS). Installing Git..." + nix-env -iA nixpkgs.git + ;; + guix) + log_message "INFO" "Detected guix (Guix). Installing Git..." + guix package -i git + ;; + pkg) + log_message "INFO" "Detected pkg (Termux). Installing Git..." + pkg install git + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + exit 1 + ;; + esac + ;; + Darwin) + log_message "INFO" "Detected macOS. Installing Git via Homebrew..." + if ! command -v brew &> /dev/null; then + log_message "ERROR" "${red_fg_strong}Homebrew not installed. Install it first: https://brew.sh/${reset}" + exit 1 + fi + brew install git + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + exit 1 + ;; + esac log_message "INFO" "${green_fg_strong}Git is installed.${reset}" else - echo -e "${blue_fg_strong}[INFO] Git is already installed.${reset}" + log_message "INFO" "${blue_fg_strong}Git is already installed.${reset}" fi } -# Change the current directory to 'sillytavern' folder -cd "$(dirname "$0")/SillyTavern" || exit 1 - -# Check for updates -git fetch origin - -update_status="Up to Date" -current_branch="$(git branch --show-current)" - -# Check for updates -if [[ "$(git rev-list HEAD...origin/$current_branch)" ]]; then - update_status="Update Available" -fi - -# Go back to base dir -cd .. - -############################################################ -################## HOME - FRONTEND ######################### -############################################################ -home() { - echo -e "\033]0;SillyTavern [HOME]\007" - clear - echo -e "${blue_fg_strong}/ Home${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Start SillyTavern" - echo "2. Start Extras" - echo "3. Start XTTS" - echo "4. Update" - echo "5. Backup" - echo "6. Switch branch" - echo "7. Toolbox" - echo "8. Support" - echo "0. Exit" - - echo "======== VERSION STATUS ========" - echo -e "SillyTavern branch: ${cyan_fg_strong}$current_branch${reset}" - echo -e "Sillytavern: $update_status" - echo -e "Launcher: V1.0.8" - echo "================================" - - read -p "Choose Your Destiny: " home_choice - - # Default to choice 1 if no input is provided - if [ -z "$home_choice" ]; then - home_choice=1 - fi - -################## HOME - BACKEND ######################### - case $home_choice in - 1) start_st ;; - 2) start_extras ;; - 3) start_xtts ;; - 4) update ;; - 5) backup_menu ;; - 6) switch_branch_menu ;; - 7) toolbox ;; - 8) support ;; - 0) exit ;; - *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" - read -p "Press Enter to continue..." - home ;; - esac -} - # Function to check if Node.js is installed check_nodejs() { @@ -211,59 +345,7 @@ check_nodejs() { } -# Function to find a suitable terminal emulator -find_terminal() -{ - for term in "$TERM" - do - if command -v "$term" > /dev/null 2>&1; then - echo "$term" - return 0 - fi - done - for terminal in "$TERMINAL" - do - if command -v "$terminal" > /dev/null 2>&1; then - echo "$terminal" - return 0 - fi - done - # Return a default terminal if none is found - echo "x-terminal-emulator" - return 1 -} -# Function to start SillyTavern -start_st() -{ - check_nodejs - cd "SillyTavern" || exit 1 - - #if LAUNCH_NEW_WIN is set to 0, SillyTavern will launch in the same window - if [ "$LAUNCH_NEW_WIN" = "0" ]; then - log_message "INFO" "SillyTavern launched" - ./start.sh - else - log_message "INFO" "SillyTavern launched in a new window." - # Find a suitable terminal - local detected_terminal - detected_terminal=$(find_terminal) - log_message "INFO" "Found terminal: $detected_terminal" - # Enable read p command for troubleshooting - # read -p "Press Enter to continue..." - - # Start SillyTavern in the detected terminal - if [ "$(uname)" == "Darwin" ]; then - log_message "INFO" "Detected macOS. Opening new Terminal window." - open -a Terminal "start.sh" - else - exec "$detected_terminal" -e "./start.sh" & - fi - fi - - cd .. - home -} # Function to start SillyTavern with Extras start_extras() { @@ -352,7 +434,7 @@ start_xtts() { # Function to update update() { - echo -e "\033]0;SillyTavern [UPDATE]\007" + echo -e "\033]0;STL [UPDATE]\007" log_message "INFO" "Updating SillyTavern-Launcher..." git pull --rebase --autostash @@ -396,190 +478,1149 @@ update() { create_backup() { - echo -e "\033]0;SillyTavern [CREATE-BACKUP]\007" - # Define the backup file name with a formatted date and time - formatted_date=$(date +'%Y-%m-%d_%H%M') - backup_file="backups/backup_$formatted_date.tar.gz" + echo -e "\033]0;STL [CREATE BACKUP]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Toolbox / Backup / Create Backup |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" - # Create the backup using tar - tar -czvf "$backup_file" \ - "public/assets/" \ - "public/Backgrounds/" \ - "public/Characters/" \ - "public/Chats/" \ - "public/context/" \ - "public/Group chats/" \ - "public/Groups/" \ - "public/instruct/" \ - "public/KoboldAI Settings/" \ - "public/movingUI/" \ - "public/NovelAI Settings/" \ - "public/OpenAI Settings/" \ - "public/QuickReplies/" \ - "public/TextGen Settings/" \ - "public/themes/" \ - "public/User Avatars/" \ - "public/user/" \ - "public/worlds/" \ - "public/settings.json" \ - "secrets.json" + # Scan for user folders + user_folders=() + for dir in "$st_install_path/data"/*; do + if [ -d "$dir" ]; then + folder_name=$(basename "$dir") + if [[ "$folder_name" != "_storage" && "$folder_name" != "_uploads" ]]; then + user_folders+=("$folder_name") + fi + fi + done - echo -e "${green_fg_strong}Backup created successfully!${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Detected Accounts |${reset}" + for ((i = 0; i < ${#user_folders[@]}; i++)); do + echo -e " $((i + 1)). ${yellow_fg_strong}${user_folders[$i]}${reset}" + done + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Cancel" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + # If only one user folder is found, skip the selection + if [ ${#user_folders[@]} -eq 1 ]; then + selected_user_folder="${user_folders[0]}" + else + echo + read -p "Select a folder to backup: " user_choice + + # Check if the user wants to exit + if [ "$user_choice" -eq 0 ]; then + backup + fi + + # Validate user input + if [[ "$user_choice" -lt 1 || "$user_choice" -gt ${#user_folders[@]} ]]; then + echo -e "${red_fg_strong}[ERROR] Invalid selection. Please enter a number between 1 and ${#user_folders[@]}, or press 0 to cancel.${reset}" + read -p "Press Enter to continue..." + create_backup + return + fi + + selected_user_folder="${user_folders[$((user_choice - 1))]}" + fi + + # Prompt user for custom name + read -p " Give backup file a custom name? (Default is st_backup_DATE_TIME.7z) [Y/N]: " rename_choice + rename_choice=$(echo "$rename_choice" | tr '[:upper:]' '[:lower:]') + + # Check if the user wants to exit + if [[ "$rename_choice" == "0" ]]; then + backup + fi + + if [[ "$rename_choice" == "y" ]]; then + read -p "Enter custom name for backup file (without extension): " custom_name + backup_filename="st_backup_${custom_name}.7z" + else + # Get current date and time + formatted_date=$(date +"%Y-%m-%d_%H-%M") + backup_filename="st_backup_${formatted_date}.7z" + fi + + # Create a backup using 7zip + if ! command -v 7z &> /dev/null; then + echo -e "${red_fg_strong}[ERROR] 7z is not installed. Please install it to create backups.${reset}" + read -p "Press Enter to continue..." + backup + fi + + 7z a "$st_backup_path/$backup_filename" "$st_install_path/data/$selected_user_folder/*" > /dev/null + + if [ $? -eq 0 ]; then + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} ${green_fg_strong}Backup created at $st_backup_path/$backup_filename${reset}" + else + echo -e "${red_fg_strong}[ERROR] Backup creation failed.${reset}" + fi read -p "Press Enter to continue..." - backup_menu + backup } restore_backup() { - echo -e "\033]0;SillyTavern [RESTORE-BACKUP]\007" - # List available backups - echo "List of available backups:" - echo "========================" + echo -e "\033]0;STL [RESTORE BACKUP]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Toolbox / Backup / Restore Backup |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" - backup_count=0 + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Available Backups |${reset}" backup_files=() + backup_count=0 - for file in backups/backup_*.tar.gz; do - backup_count=$((backup_count + 1)) - backup_files+=("$file") - echo -e "$backup_count. ${cyan_fg_strong}$(basename "$file")${reset}" + for file in "$st_backup_path"/st_backup_*.7z; do + if [ -f "$file" ]; then + backup_count=$((backup_count + 1)) + backup_files+=("$(basename "$file" .7z)") + echo -e " $backup_count. ${yellow_fg_strong}$(basename "$file" .7z)${reset}" + fi done - echo "========================" - read -p "Enter the number of the backup to restore: " restore_choice - - if [ "$restore_choice" -ge 1 ] && [ "$restore_choice" -le "$backup_count" ]; then - selected_backup="${backup_files[restore_choice - 1]}" - echo "Restoring backup $selected_backup..." - - # Extract the contents of the backup to a temporary directory - temp_dir=$(mktemp -d) - tar -xzvf "$selected_backup" -C "$temp_dir" - - # Copy the restored files to the appropriate location - rsync -av "$temp_dir/public/" "public/" - - # Clean up the temporary directory - rm -r "$temp_dir" - - echo -e "${green_fg_strong}$selected_backup restored successfully.${reset}" - else - echo -e "${yellow_fg_strong}WARNING: Invalid backup number. Please insert a valid number.${reset}" + if [ "$backup_count" -eq 0 ]; then + echo -e " ${red_fg_strong}No backups found.${reset}" fi + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Cancel" + echo + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + # Prompt user to select a backup + read -p " Select backup to restore: " restore_choice + + # Check if the user wants to cancel + if [[ "$restore_choice" == "0" ]]; then + backup + fi + + # Validate user input + if [[ "$restore_choice" -lt 1 || "$restore_choice" -gt "$backup_count" ]]; then + echo -e "${red_fg_strong}[ERROR] Invalid selection. Please enter a number between 1 and $backup_count, or press 0 to cancel.${reset}" + read -p "Press Enter to continue..." + restore_backup + return + fi + + # Get the selected backup file + selected_backup="${backup_files[$((restore_choice - 1))]}" + + # Restore the backup + echo "Restoring backup $selected_backup..." + + # Create a temporary directory for extraction + temp_dir=$(mktemp -d) + + # Extract the backup to the temporary directory + if ! command -v 7z &> /dev/null; then + echo -e "${red_fg_strong}[ERROR] 7z is not installed. Please install it to restore backups.${reset}" + read -p "Press Enter to continue..." + backup + fi + + 7z x "$st_backup_path/$selected_backup.7z" -o"$temp_dir" -aoa > /dev/null + + if [ $? -ne 0 ]; then + echo -e "${red_fg_strong}[ERROR] Failed to extract backup.${reset}" + rm -rf "$temp_dir" + read -p "Press Enter to continue..." + backup + fi + + # Copy the extracted data to the SillyTavern data directory + if [ -d "$temp_dir/data" ]; then + cp -r "$temp_dir/data/"* "$st_install_path/data/" + else + echo -e "${red_fg_strong}[ERROR] Backup does not contain a valid data directory.${reset}" + rm -rf "$temp_dir" + read -p "Press Enter to continue..." + backup + fi + + # Clean up the temporary directory + rm -rf "$temp_dir" + + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} ${green_fg_strong}$selected_backup restored successfully.${reset}" read -p "Press Enter to continue..." - backup_menu + backup } ############################################################ ################# BACKUP - FRONTEND ######################## ############################################################ -backup_menu() { - echo -e "\033]0;SillyTavern [BACKUP]\007" +backup() { + echo -e "\033]0;STL [BACKUP]\007" clear - echo -e "${blue_fg_strong}/ Home / Backup${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Create Backup" - echo "2. Restore Backup" - echo "0. Back to Home" + echo -e "${blue_fg_strong}| > / Home / Toolbox / Backup |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Create Backup" + echo " 2. Restore Backup" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" - read -p "Choose Your Destiny: " backup_choice + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " backup_choice ################# BACKUP - BACKEND ######################## case $backup_choice in 1) create_backup ;; 2) restore_backup ;; - 0) home ;; + 0) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." - backup_menu ;; + backup ;; esac } +######################################################################################## +######################################################################################## +####################### EDITOR FUNCTIONS ############################################## +######################################################################################## +######################################################################################## + +# Function to print module options with color based on their status +printModule() { + if [ "$2" == "true" ]; then + echo -e "\e[32;1m$1 [Enabled]\e[0m" + else + echo -e "\e[31;1m$1 [Disabled]\e[0m" + fi +} + +# Function to edit extras modules +edit_extras_modules() { + echo -e "\033]0;STL [EDIT-MODULES]\007" + clear + echo -e "${blue_fg_strong}/ Home / Toolbox / Editor / Edit Extras Modules${reset}" + echo "-------------------------------------" + echo "Choose extras modules to enable or disable (e.g., \"1 2 4\" to enable Cuda, RVC, and Caption)" + + # Display module options with colors based on their status + printModule "1. Cuda (--gpu 0 --cuda --cuda-device=0)" "$cuda_trigger" + printModule "2. RVC (--enable-modules=rvc --rvc-save-file --max-content-length=1000)" "$rvc_trigger" + printModule "3. talkinghead (--enable-modules=talkinghead)" "$talkinghead_trigger" + printModule "4. caption (--enable-modules=caption)" "$caption_trigger" + printModule "5. summarize (--enable-modules=summarize)" "$summarize_trigger" + printModule "6. listen (--listen)" "$listen_trigger" + printModule "7. Edge TTS (--enable-modules=edge-tts)" "$edge_tts_trigger" + echo "0. Back to Toolbox" + + set "python_command=" + + read -p "Choose modules to enable/disable (1-6): " module_choices + + # Handle the user's module choices and construct the Python command + for i in $module_choices; do + case $i in + 1) [ "$cuda_trigger" == "true" ] && cuda_trigger=false || cuda_trigger=true ;; + 2) [ "$rvc_trigger" == "true" ] && rvc_trigger=false || rvc_trigger=true ;; + 3) [ "$talkinghead_trigger" == "true" ] && talkinghead_trigger=false || talkinghead_trigger=true ;; + 4) [ "$caption_trigger" == "true" ] && caption_trigger=false || caption_trigger=true ;; + 5) [ "$summarize_trigger" == "true" ] && summarize_trigger=false || summarize_trigger=true ;; + 6) [ "$listen_trigger" == "true" ] && listen_trigger=false || listen_trigger=true ;; + 7) [ "$edge_tts_trigger" == "true" ] && edge_tts_trigger=false || edge_tts_trigger=true ;; + 0) toolbox ;; + esac + done + + # Save the module flags to modules.txt + modules_file="$(dirname "$0")/modules.txt" + echo "cuda_trigger=$cuda_trigger" > "$modules_file" + echo "rvc_trigger=$rvc_trigger" >> "$modules_file" + echo "talkinghead_trigger=$talkinghead_trigger" >> "$modules_file" + echo "caption_trigger=$caption_trigger" >> "$modules_file" + echo "summarize_trigger=$summarize_trigger" >> "$modules_file" + echo "listen_trigger=$listen_trigger" >> "$modules_file" + echo "edge_tts_trigger=$edge_tts_trigger" >> "$modules_file" + + # Compile the Python command + python_command="python server.py" + [ "$listen_trigger" == "true" ] && python_command+=" --listen" + [ "$cuda_trigger" == "true" ] && python_command+=" --gpu 0 --cuda --cuda-device=0 " + [ "$rvc_trigger" == "true" ] && python_command+=" --rvc-save-file --max-content-length=1000" + modules_enable="" + [ "$talkinghead_trigger" == "true" ] && modules_enable+="talkinghead," + [ "$caption_trigger" == "true" ] && modules_enable+="caption," + [ "$summarize_trigger" == "true" ] && modules_enable+="summarize," + [ "$edge_tts_trigger" == "true" ] && modules_enable+="edge-tts," + + # Remove the last comma from modules_enable + modules_enable="${modules_enable%,}" + + # Save the constructed Python command to modules.txt for testing + echo "start_command=$python_command --enable-modules=$modules_enable" >> "$modules_file" + edit_extras_modules +} + +# Function to edit XTTS modules +edit_xtts_modules() { + echo -e "\033]0;STL [EDIT-XTTS-MODULES]\007" + clear + echo -e "${blue_fg_strong}/ Home / Toolbox / Editor / Edit XTTS Modules${reset}" + echo "-------------------------------------" + echo "Choose XTTS modules to enable or disable (e.g., "1 2 4" to enable Cuda, hs, and cache)" + + # Display module options with colors based on their status + printModule "1. cuda (--device cuda)" "$xtts_cuda_trigger" + printModule "2. hs (-hs 0.0.0.0)" "$xtts_hs_trigger" + printModule "3. deepspeed (--deepspeed)" "$xtts_deepspeed_trigger" + printModule "4. cache (--use-cache)" "$xtts_cache_trigger" + printModule "5. listen (--listen)" "$xtts_listen_trigger" + printModule "6. model (--model-source local)" "$xtts_model_trigger" + echo "0. Back to Editor"s + + set "python_command=" + + read -p "Choose modules to enable/disable (1-6): " module_choices + + # Handle the user's module choices and construct the Python command + for i in $module_choices; do + case $i in + 1) [ "$xtts_cuda_trigger" == "true" ] && xtts_cuda_trigger=false || xtts_cuda_trigger=true ;; + 2) [ "$xtts_hs_trigger" == "true" ] && xtts_hs_trigger=false || xtts_hs_trigger=true ;; + 3) [ "$xtts_deepspeed_trigger" == "true" ] && xtts_deepspeed_trigger=false || xtts_deepspeed_trigger=true ;; + 4) [ "$xtts_cache_trigger" == "true" ] && xtts_cache_trigger=false || xtts_cache_trigger=true ;; + 5) [ "$xtts_listen_trigger" == "true" ] && xtts_listen_trigger=false || xtts_listen_trigger=true ;; + 6) [ "$xtts_model_trigger" == "true" ] && xtts_model_trigger=false || xtts_model_trigger=true ;; + 0) editor ;; + esac + done + + # Save the module flags to modules-xtts.txt + modules_file="$(dirname "$0")/modules-xtts.txt" + echo "xtts_cuda_trigger=$xtts_cuda_trigger" > "$modules_file" + echo "xtts_hs_trigger=$xtts_hs_trigger" >> "$modules_file" + echo "xtts_deepspeed_trigger=$xtts_deepspeed_trigger" >> "$modules_file" + echo "xtts_cache_trigger=$xtts_cache_trigger" >> "$modules_file" + echo "xtts_listen_trigger=$xtts_listen_trigger" >> "$modules_file" + echo "xtts_model_trigger=$xtts_model_trigger" >> "$modules_file" + + # Compile the Python command + python_command="python server.py" + [ "$xtts_cuda_trigger" == "true" ] && python_command+=" --device cuda" + [ "$xtts_hs_trigger" == "true" ] && python_command+=" -hs 0.0.0.0" + [ "$xtts_deepspeed_trigger" == "true" ] && python_command+=" --deepspeed" + [ "$xtts_cache_trigger" == "true" ] && python_command+=" --use-cache" + [ "$xtts_listen_trigger" == "true" ] && python_command+=" --listen" + [ "$xtts_model_trigger" == "true" ] && python_command+=" --model-source local" + + # Save the constructed Python command to modules.txt for testing + echo "start_command=$python_command" >> "$modules_file" + edit_xtts_modules +} + + +# Function to edit environment variables +edit_env_var() { + # Open the environment variables file for editing + if [ -f ~/.bashrc ]; then + # Use your preferred text editor (e.g., nano, vim, or gedit) + nano ~/.bashrc + else + echo "Environment file not found. Create or specify the correct file path." + fi + + # Optionally, ask the user to reload the environment + read -p "Would you like to reload the environment? [Y/N]: " reload + if [ "$reload" = "Y" ] || [ "$reload" = "y" ]; then + source ~/.bashrc # Reload the environment (may vary based on your shell) + echo "Environment reloaded." + fi + + editor_core_utilities +} + + +edit_st_config() { + # Check if nano is available + if ! command -v nano &>/dev/null; then + echo "Error: Nano is not installed. Please install Nano to edit config.yaml" + editor_core_utilities + fi + # Open config.yaml file in nano + nano "$st_install_path/config.yaml" + + editor_core_utilities +} + + +editor_text_completion() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + editor +} + +editor_voice_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + editor +} + +editor_image_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + editor +} + +edit_extras_modules() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + editor_core_utilities + +} +create_st_ssl() { + # Check if a specific argument is passed to detect if called by another script + local pause_required=true + local silent_mode=false + if [ -n "$1" ]; then + silent_mode=true + fi + + # Redirect output to /dev/null if in silent mode + if [ "$silent_mode" = true ]; then + local output_redirection=">/dev/null 2>&1" + else + local output_redirection="" + fi + + # Set the SSL certificate directory and files + local CERT_DIR="$st_install_path/certs" + local CERT_FILE="$CERT_DIR/cert.pem" + local KEY_FILE="$CERT_DIR/privkey.pem" + local CERT_INFO_FILE="$CERT_DIR/SillyTavernSSLInfo.txt" + local ERROR_LOG="$CERT_DIR/error_log.txt" + + # Check if the SillyTavern directory exists + if [ ! -d "$st_install_path" ]; then + echo "Please install SillyTavern first." + if [ "$pause_required" = true ]; then + read -p "Press Enter to continue..." + fi + editor_core_utilities + fi + + # Create the SSL certificate directory if it doesn't exist + if [ ! -d "$CERT_DIR" ]; then + mkdir -p "$CERT_DIR" + eval "echo Created directory $CERT_DIR $output_redirection" + else + eval "echo Directory $CERT_DIR already exists. $output_redirection" + fi + + # Check if the certificate already exists and delete it if it does + if [ -f "$CERT_FILE" ]; then + rm "$CERT_FILE" + eval "echo Existing certificate deleted. $output_redirection" + fi + + if [ -f "$KEY_FILE" ]; then + rm "$KEY_FILE" + eval "echo Existing key deleted. $output_redirection" + fi + + # Find the OpenSSL binary + local openssl_path=$(which openssl) + if [ -z "$openssl_path" ]; then + echo "OpenSSL is not installed. Please install it first." + if [ "$pause_required" = true ]; then + read -p "Press Enter to continue..." + fi + editor_core_utilities + fi + + eval "echo OpenSSL is located at: $openssl_path $output_redirection" + + # Generate the self-signed certificate in PEM format + eval "echo Generating self-signed certificate... $output_redirection" + eval "$openssl_path req -x509 -newkey rsa:4096 -keyout \"$KEY_FILE\" -out \"$CERT_FILE\" -days 825 -nodes -subj \"/CN=127.0.0.1\" $output_redirection" + + if [ $? -ne 0 ]; then + echo "An error occurred. Please check the console output for details." + echo "[$(date)] An error occurred during certificate generation." >> "$ERROR_LOG" + if [ "$pause_required" = true ]; then + read -p "Press Enter to continue..." + fi + editor_core_utilities + fi + + eval "echo Certificate generation complete. $output_redirection" + + # Calculate the expiration date (today + 825 days) and format as YYYY-MM-DD + local exp_date=$(date -d "+825 days" +"%Y-%m-%d") + + # Store the certificate and key path, and expiration date in the text file + { + echo "$CERT_FILE" + echo "$KEY_FILE" + echo "SSL Expiration Date (YYYY-MM-DD): $exp_date" + } > "$CERT_INFO_FILE" + + eval "echo Certificate and key paths and expiration date stored in $CERT_INFO_FILE. $output_redirection" + + echo "Done." + if [ "$pause_required" = true ]; then + read -p "Press Enter to continue..." + fi + editor_core_utilities +} + +delete_st_ssl() { + CERTS_DIR="$st_install_path/certs" + if [ -d "$CERTS_DIR" ]; then + log_message "INFO" "Removing $CERTS_DIR..." + rm -rf "$CERTS_DIR" + if [ $? -eq 0 ]; then + echo -e "${green_fg_strong}certs directory successfully deleted.${reset}" + else + log_message "ERROR" "Failed to delete certs directory. Please check permissions." + fi + else + log_message "INFO" "No SSL certificates found. Nothing to delete." + fi + read -p "Press Enter to continue..." + editor_core_utilities +} + + +config_tailscale() { + echo -e "\033]0;STL [TAILSCALE CONFIGURATION]\007" + clear + + echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer / Core Utilities / Tailscale${reset}" + echo -e "${blue_fg_strong}============================================================================================${reset}" + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + + # Calculate the path to the logs folder based on the current script location + log_dir="$(dirname "$(readlink -f "$0")")/../../../logs" + log_file="$log_dir/tailscale_status.txt" + + # Check if the log file exists before attempting to clear it + if [ -f "$log_file" ]; then + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Clearing existing log file..." + > "$log_file" + else + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Log file does not exist, no need to clear." + fi + + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Configuring Tailscale..." + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Running Tailscale login..." + + tailscale up + + if [ $? -eq 0 ]; then + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Tailscale configuration successful." + + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 1. Find Tailscale SillyTavern Remote URLs" + echo " 0. Back" + + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + read -p " Choose Your Destiny: " choice + + case $choice in + 1) + echo + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Fetching Tailscale status..." + + # Fetch Tailscale status and write to log file + tailscale status --json | jq -r '.Self | .TailscaleIPs[0], .HostName, .DNSName' > "$log_file" + + # Read values from the log file + mapfile -t tailscale_info < "$log_file" + ip4="${tailscale_info[0]}" + hostName="${tailscale_info[1]}" + dnsName="${tailscale_info[2]}" + + # Remove trailing period from dnsName if it exists + dnsName="${dnsName%.}" + + echo -e "${blue_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Tailscale Remote SillyTavern URLs (if you changed your SillyTavern Port # change 8000 to that new port):" + echo -e "${cyan_fg_strong}IP4:${reset} http://$ip4:8000" + echo -e "${cyan_fg_strong}Machine Name:${reset} http://$hostName:8000" + echo -e "${cyan_fg_strong}MagicDNS Name:${reset} http://$dnsName:8000" + echo -e "${blue_fg_strong}____________________________________________________________________________________________${reset}" + + # Prompt the user to open the additional config instructions page + read -p "Do you want to open the additional configuration instructions page (Y/N)? " userChoice + if [[ "$userChoice" =~ ^[Yy]$ ]]; then + url="https://sillytavernai.com/tailscale-config/?HostName=$hostName&DNSName=$dnsName&IP4=$ip4#STL" + xdg-open "$url" + else + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Skipping additional configuration instructions." + fi + ;; + 0) + echo -e "${blue_bg}[$(date '+%H:%M:%S')]${reset} ${blue_fg_strong}[INFO]${reset} Returning to Home..." + editor_core_utilities + ;; + *) + echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + config_tailscale + ;; + esac + else + echo -e "${red_bg}[$(date +%T)]${reset} ${red_fg_strong}[ERROR] Tailscale configuration failed.${reset}" + read -p "Press Enter to continue..." + editor_core_utilities + fi + + read -p "Press Enter to continue..." + config_tailscale +} + +editor_core_utilities() { + echo -e "\033]0;STL [EDITOR CORE UTILITIES]\007" + clear + + SSL_INFO_FILE="$st_install_path/certs/SillyTavernSSLInfo.txt" + sslOption="2. Generate & Use Self-Signed SSL for SillyTavern" + sslDeleteOption="" # Initialize delete option as empty + + # Check if SSL exists and populate options + if [ -f "$SSL_INFO_FILE" ]; then + expDate=$(sed -n '3p' "$SSL_INFO_FILE") + sslOption="2. Regenerate SillyTavern SSL - $expDate" + sslDeleteOption="222. Delete Generated SSL" + fi + + echo -e "${blue_fg_strong}| > / Home / Toolbox / Editor / Core Utilities |${reset}" + echo -e "${blue_fg_strong}============================================================================================${reset}" + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + + echo " 1. Edit SillyTavern config.yaml" + echo " 3. Edit Extras" + echo " 4. Edit Environment Variables" + echo " 5. View Tailscale configuration" + + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| SSL Options |${reset}" + echo -e " $sslOption" + [ -n "$sslDeleteOption" ] && echo -e ${yellow_fg_strong}" $sslDeleteOption${reset}" # Show delete option only if SSL exists + echo -e " 223. Open SSL documentation" + + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + + echo -e "${cyan_fg_strong}____________________________________________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + read -p " Choose Your Destiny: " editor_core_utilities_choice + + case $editor_core_utilities_choice in + 1) edit_st_config ;; + 2) create_st_ssl ;; + 3) edit_extras_modules ;; + 4) edit_env_var ;; + 5) config_tailscale ;; + 222) delete_st_ssl ;; + 223) xdg-open "https://sillytavernai.com/launcher-ssl" ; editor_core_utilities ;; + 0) editor ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + editor_core_utilities ;; + esac +} + +############################################################ +############## EDITOR - FRONTEND ########################### +############################################################ +editor() { + echo -e "\033]0;STL [EDITOR]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Toolbox / Editor |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Text Completion" + echo " 2. Voice Generation" + echo " 3. Image Generation" + echo " 4. Core Utilities" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " editor_choice + +################# EDITOR - BACKEND ################ + case $editor_choice in + 1) editor_text_completion ;; + 2) editor_voice_generation ;; + 3) editor_image_generation ;; + 4) editor_core_utilities ;; + 0) toolbox ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + editor ;; + esac +} + +######################################################################################## +######################################################################################## +####################### TROUBLESHOOTING FUNCTIONS ##################################### +######################################################################################## +######################################################################################## +remove_node_modules() { + log_message "INFO" "Removing node_modules folder..." + rm -rf "$st_install_path/node_modules" + log_message "INFO" "node_modules successfully removed." + read -p "Press Enter to continue..." + troubleshooting +} + +remove_pip_cache() { + log_message "INFO" "Clearing pip cache..." + pip cache purge + log_message "INFO" "pip cache cleared successfully." + read -p "Press Enter to continue..." + troubleshooting +} + +fix_github_conflicts() { + log_message "INFO" "Trying to resolve unresolved conflicts in the working directory or unmerged files..." + git -C "$st_install_path" merge --abort + git -C "$st_install_path" reset --hard + git -C "$st_install_path" pull --rebase --autostash + read -p "Press Enter to continue..." + troubleshooting +} + +export_system_info() { + log_message "INFO" "Exporting system information..." + lshw > "$(dirname "$0")/system_info.txt" + log_message "INFO" "You can find the system_info.txt at: $(dirname "$0")/system_info.txt" + read -p "Press Enter to continue..." + troubleshooting +} + +find_app_port() { + echo -e "\033]0;STL [FIND APP PORT]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Troubleshooting & Support / Find App Port |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Cancel" + + # Prompt for port number if not provided + if [ -z "$1" ]; then + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Insert port number: " port_choice + else + port_choice="$1" + fi + + # Check if the user wants to cancel + if [[ "$port_choice" == "0" ]]; then + troubleshooting + fi + + # Validate input: Check if it's a number + if ! [[ "$port_choice" =~ ^[0-9]+$ ]]; then + echo -e "${red_bg}[$(date +%T)]${reset} ${red_fg_strong}[ERROR] Invalid input: Not a number.${reset}" + read -p "Press Enter to continue..." + troubleshooting + return + fi + + # Validate port range + if [ "$port_choice" -gt 65535 ]; then + echo -e "${red_bg}[$(date +%T)]${reset} ${red_fg_strong}[ERROR] Port out of range. There are only 65,535 possible port numbers.${reset}" + echo "[0-1023]: These ports are reserved for system services or commonly used protocols." + echo "[1024-49151]: These ports can be used by user processes or applications." + echo "[49152-65535]: These ports are available for use by any application or service on the system." + read -p "Press Enter to continue..." + troubleshooting + return + fi + + echo -e "${blue_bg}[$(date +%T)]${reset} ${blue_fg_strong}[INFO]${reset} Searching for application using port: $port_choice..." + + # Find the PID of the process using the port + pid=$(lsof -i :"$port_choice" -t) + if [ -n "$pid" ]; then + app_name=$(ps -p "$pid" -o comm=) + echo -e "Application Name: ${cyan_fg_strong}$app_name${reset}" + echo -e "PID of Port $port_choice: ${cyan_fg_strong}$pid${reset}" + + # Fetch the page title for the specified port + fetch_page_title "$port_choice" + if [ -n "$PAGE_TITLE" ]; then + echo -e "Title of Application: ${cyan_fg_strong}$PAGE_TITLE${reset}" + else + echo -e "${yellow_bg}[$(date +%T)]${reset} ${yellow_fg_strong}[WARN]${reset} Could not retrieve page title." + fi + else + echo -e "${yellow_bg}[$(date +%T)]${reset} ${yellow_fg_strong}[WARN]${reset} Port: $port_choice not found." + fi + + read -p "Press Enter to continue..." + find_app_port +} + +# Function to fetch the page title for a given port +fetch_page_title() { + local port="$1" + local url="http://localhost:$port" + + # Use curl to fetch the page title + PAGE_TITLE=$(curl -s "$url" | grep -oP '(?<=).*?(?=)') +} + + +onboarding_flow() { + read -p "Enter new value for Onboarding Flow (true/false): " onboarding_flow_value + if [[ "$onboarding_flow_value" != "true" && "$onboarding_flow_value" != "false" ]]; then + log_message "WARN" "Invalid input. Please enter 'true' or 'false'." + read -p "Press Enter to continue..." + onboarding_flow + fi + sed -i "s/\"firstRun\": .*/\"firstRun\": $onboarding_flow_value,/" "$st_install_path/public/settings.json" + log_message "INFO" "Value of 'firstRun' in settings.json has been updated to $onboarding_flow_value." + read -p "Press Enter to continue..." + troubleshooting +} + +discord_servers_menu() { + echo -e "\033]0;STL [DISCORD SERVERS]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Troubleshooting & Support / Discord Servers |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo " 1. Join SillyTavern" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Discord - LLM Backends: |${reset}" + echo " 2. Join TabbyAPI" + echo " 3. Join KoboldAI" + echo " 4. Join Text Generation WEBUI ooba" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Discord - Cloud API: |${reset}" + echo " 5. Join Mancer" + echo " 6. Join OpenRouter" + echo " 7. Join AI Horde" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Discord - Model Devs & Research: |${reset}" + echo " 8. Join TheBloke" + echo " 9. Join PygmalionAI" + echo " 10. Join Nous Research" + echo " 11. Join RWKV" + echo " 12. Join EleutherAI" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + read -p " Choose Your Destiny: " discord_servers_choice + + ################ DISCORD SERVERS - BACKEND ################ + case $discord_servers_choice in + 1) discord_sillytavern ;; + 2) discord_tabbyapi ;; + 3) discord_koboldai ;; + 4) discord_textgenwebuiooba ;; + 5) discord_mancer ;; + 6) discord_openrouter ;; + 7) discord_aihorde ;; + 8) discord_thebloke ;; + 9) discord_pygmalionai ;; + 10) discord_nousresearch ;; + 11) discord_rwkv ;; + 12) discord_eleutherai ;; + 0) troubleshooting ;; + *) + echo -e "${red_fg_strong}[ERROR] Invalid input. Please enter a valid number.${reset}" + read -p "Press Enter to continue..." + discord_servers_menu + ;; + esac +} + +# Discord server functions +discord_sillytavern() { + xdg-open "https://discord.gg/sillytavern" + discord_servers_menu +} + +discord_tabbyapi() { + xdg-open "https://discord.gg/sYQxnuD7Fj" + discord_servers_menu +} + +discord_koboldai() { + xdg-open "https://discord.gg/UCyXV7NssH" + discord_servers_menu +} + +discord_textgenwebuiooba() { + xdg-open "https://discord.gg/jwZCF2dPQN" + discord_servers_menu +} + +discord_mancer() { + xdg-open "https://discord.gg/6DZaU9Gv9F" + discord_servers_menu +} + +discord_openrouter() { + xdg-open "https://discord.gg/H9tjZYgauh" + discord_servers_menu +} + +discord_aihorde() { + xdg-open "https://discord.gg/3DxrhksKzn" + discord_servers_menu +} + +discord_thebloke() { + xdg-open "https://discord.gg/Jq4vkcDakD" + discord_servers_menu +} + +discord_pygmalionai() { + xdg-open "https://discord.gg/pygmalionai" + discord_servers_menu +} + +discord_nousresearch() { + xdg-open "https://discord.gg/jqVphNsB4H" + discord_servers_menu +} + +discord_rwkv() { + xdg-open "https://discord.gg/bDSBUMeFpc" + discord_servers_menu +} + +discord_eleutherai() { + xdg-open "https://discord.gg/zBGx3azzUn" + discord_servers_menu +} + +############################################################ +############## TROUBLESHOOTING - FRONTEND ################## +############################################################ +troubleshooting() { + echo -e "\033]0;STL [TROUBLESHOOTING SUPPORT]\007" + clear + echo -e "${blue_fg_strong}| > / Home / Troubleshooting & Support |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Troubleshooting & Repair Options |${reset}" + echo " 1. Remove node_modules folder" + echo " 2. Clear npm cache" + echo " 3. Clear pip cache" + echo " 4. Fix unresolved conflicts or unmerged files [SillyTavern]" + echo " 5. Export system info" + echo " 6. Find what app is using port" + echo " 7. Set Onboarding Flow" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Support Options: |${reset}" + echo " 8. Report an Issue" + echo " 9. SillyTavern Documentation" + echo " 10. Discord servers" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " troubleshooting_choice + +################# TROUBLESHOOTING - BACKEND ################ + case $troubleshooting_choice in + 1) remove_node_modules ;; + 2) remove_npm_cache ;; + 3) remove_pip_cache ;; + 4) fix_github_conflicts ;; + 5) export_system_info ;; + 6) find_app_port ;; + 7) onboarding_flow ;; + 8) issue_report ;; + 9) documentation ;; + 10) discord_servers_menu ;; + 0) home ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + troubleshooting ;; + esac +} + +######################################################################################## +######################################################################################## +####################### SUPPORT FUNCTIONS ############################################# +######################################################################################## +######################################################################################## +issue_report() { + if [ "$EUID" -eq 0 ]; then + log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" + else + if [ "$(uname -s)" == "Darwin" ]; then + open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose + else + xdg-open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose + fi + fi + read -p "Press Enter to continue..." + troubleshooting +} + +documentation() { + if [ "$EUID" -eq 0 ]; then + log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" + else + if [ "$(uname -s)" == "Darwin" ]; then + open https://docs.sillytavern.app/ + else + xdg-open https://docs.sillytavern.app/ + fi + fi + read -p "Press Enter to continue..." + troubleshooting +} + + +######################################################################################## +######################################################################################## +####################### TOOLBOX MENU FUNCTIONS ######################################## +######################################################################################## +######################################################################################## + # Function to switch to the Release branch in SillyTavern switch_release_st() { log_message "INFO" "Switching to release branch..." - git switch release + git -C "$st_install_path" switch release read -p "Press Enter to continue..." - switch_branch_menu + switch_branch } # Function to switch to the Staging branch in SillyTavern switch_staging_st() { log_message "INFO" "Switching to staging branch..." - git switch staging + git -C "$st_install_path" switch staging read -p "Press Enter to continue..." - switch_branch_menu + switch_branch } ############################################################ ############## SWITCH BRANCE - FRONTEND #################### ############################################################ -switch_branch_menu() { - echo -e "\033]0;SillyTavern [SWITCH-BRANCE]\007" +switch_branch() { + echo -e "\033]0;STL [SWITCH BRANCH]\007" clear - echo -e "${blue_fg_strong}/ Home / Switch Branch${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Switch to Release - SillyTavern" - echo "2. Switch to Staging - SillyTavern" - echo "0. Back to Home" + echo -e "${blue_fg_strong}| > / Home / Toolbox / Switch Branch |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${yellow_fg_strong} ______________________________________________________________${reset}" + echo -e "${yellow_fg_strong}| Version Status |${reset}" + current_st_branch=$(git -C "$st_install_path" branch --show-current) + echo -e " SillyTavern branch: ${cyan_fg_strong}$current_st_branch${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Switch to Release - SillyTavern" + echo " 2. Switch to Staging - SillyTavern" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" - current_branch=$(git branch --show-current) - echo "======== VERSION STATUS ========" - echo -e "SillyTavern branch: ${cyan_fg_strong}$current_branch${reset}" - echo -e "Extras branch: ${cyan_fg_strong}$current_branch${reset}" - echo "================================" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" - read -p "Choose Your Destiny: " branch_choice + read -p " Choose Your Destiny: " branch_choice ################# SWITCH BRANCE - BACKEND ######################## case $branch_choice in 1) switch_release_st ;; 2) switch_staging_st ;; - 0) home ;; + 0) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." - switch_branch_menu ;; + switch_branch ;; esac } +reset_custom_shortcut() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + toolbox +} +app_launcher() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + toolbox +} + +######################################################################################## +######################################################################################## +####################### APP INSTALLER MENU FUNCTIONS ################################## +######################################################################################## +######################################################################################## # Function to install p7zip (7-Zip) install_p7zip() { if ! command -v 7z &> /dev/null; then log_message "WARN" "${yellow_fg_strong}p7zip (7-Zip) is not installed on this system${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Installing p7zip (7-Zip) using apt..." - sudo apt-get update - sudo apt-get install -y p7zip-full - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Installing p7zip (7-Zip) using yum..." - sudo yum install -y p7zip p7zip-plugins - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Installing p7zip (7-Zip) using apk..." - sudo apk add p7zip - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Installing p7zip (7-Zip) using pacman..." - sudo pacman -Sy --noconfirm p7zip - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Installing p7zip (7-Zip) using emerge..." - sudo emerge --ask app-arch/p7zip - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 - fi + case "$(grep -E '^ID=' /etc/os-release | cut -d= -f2)" in + debian|ubuntu) + # Debian/Ubuntu-based system + log_message "INFO" "Installing p7zip (7-Zip) using apt..." + sudo apt-get update + sudo apt-get install -y p7zip-full + ;; + fedora|centos|rhel) + # Red Hat/Fedora-based system + log_message "INFO" "Installing p7zip (7-Zip) using yum..." + sudo yum install -y p7zip p7zip-plugins + ;; + alpine) + # Alpine Linux-based system + log_message "INFO" "Installing p7zip (7-Zip) using apk..." + sudo apk add p7zip + ;; + arch|manjaro) + # Arch Linux-based system + log_message "INFO" "Installing p7zip (7-Zip) using pacman..." + sudo pacman -Sy --noconfirm p7zip + ;; + gentoo) + # Gentoo Linux-based system + log_message "INFO" "Installing p7zip (7-Zip) using emerge..." + sudo emerge --ask app-arch/p7zip + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" + exit 1 + ;; + esac log_message "INFO" "${green_fg_strong}p7zip (7-Zip) is installed.${reset}" else @@ -592,31 +1633,38 @@ install_ffmpeg() { if ! command -v ffmpeg &> /dev/null; then log_message "WARN" "${yellow_fg_strong}FFmpeg is not installed on this system${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Installing FFmpeg using apt..." - sudo apt-get update - sudo apt-get install -y ffmpeg - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Installing FFmpeg using yum..." - sudo yum install -y ffmpeg - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Installing FFmpeg using apk..." - sudo apk add ffmpeg - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Installing FFmpeg using pacman..." - sudo pacman -Sy --noconfirm ffmpeg - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Installing FFmpeg using emerge..." - sudo emerge --ask media-video/ffmpeg - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 - fi + case "$(grep -E '^ID=' /etc/os-release | cut -d= -f2)" in + debian|ubuntu) + # Debian/Ubuntu-based system + log_message "INFO" "Installing FFmpeg using apt..." + sudo apt-get update + sudo apt-get install -y ffmpeg + ;; + fedora|centos|rhel) + # Red Hat/Fedora-based system + log_message "INFO" "Installing FFmpeg using yum..." + sudo yum install -y ffmpeg + ;; + alpine) + # Alpine Linux-based system + log_message "INFO" "Installing FFmpeg using apk..." + sudo apk add ffmpeg + ;; + arch|manjaro) + # Arch Linux-based system + log_message "INFO" "Installing FFmpeg using pacman..." + sudo pacman -Sy --noconfirm ffmpeg + ;; + gentoo) + # Gentoo Linux-based system + log_message "INFO" "Installing FFmpeg using emerge..." + sudo emerge --ask media-video/ffmpeg + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" + exit 1 + ;; + esac log_message "INFO" "${green_fg_strong}FFmpeg is installed.${reset}" else @@ -624,37 +1672,69 @@ install_ffmpeg() { fi } -# Function to install Node.js install_nodejs() { if ! command -v node &> /dev/null; then log_message "WARN" "${yellow_fg_strong}Node.js is not installed on this system${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Installing Node.js using apt..." - curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash - - sudo apt-get install -y nodejs - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Installing Node.js using yum..." - curl -sL https://rpm.nodesource.com/setup_14.x | sudo bash - - sudo yum install -y nodejs - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Installing Node.js using apk..." - sudo apk add nodejs npm - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Installing Node.js using pacman..." - sudo pacman -Sy --noconfirm nodejs npm - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Installing Node.js using emerge..." - sudo emerge --ask nodejs - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 - fi + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + log_message "INFO" "Detected apt (Debian/Ubuntu). Installing Node.js..." + sudo apt update && sudo apt install -y nodejs npm + ;; + dnf|yum) + log_message "INFO" "Detected dnf/yum (Red Hat/Fedora). Installing Node.js..." + sudo $package_manager install -y nodejs npm + ;; + apk) + log_message "INFO" "Detected apk (Alpine). Installing Node.js..." + sudo apk add nodejs npm + ;; + pacman) + log_message "INFO" "Detected pacman (Arch). Installing Node.js..." + sudo pacman -Sy --noconfirm nodejs npm + ;; + emerge) + log_message "INFO" "Detected emerge (Gentoo). Installing Node.js..." + sudo emerge --ask nodejs npm + ;; + zypper) + log_message "INFO" "Detected zypper (openSUSE). Installing Node.js..." + sudo zypper install -y nodejs npm + ;; + xbps) + log_message "INFO" "Detected xbps (Void). Installing Node.js..." + sudo xbps-install -y nodejs npm + ;; + nix) + log_message "INFO" "Detected nix (NixOS). Installing Node.js..." + nix-env -iA nixpkgs.nodejs + ;; + guix) + log_message "INFO" "Detected guix (Guix). Installing Node.js..." + guix package -i node + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + exit 1 + ;; + esac + ;; + Darwin) + log_message "INFO" "Detected macOS. Installing Node.js via Homebrew..." + if ! command -v brew &> /dev/null; then + log_message "ERROR" "${red_fg_strong}Homebrew not installed. Install it first: https://brew.sh/${reset}" + exit 1 + fi + brew install node + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + exit 1 + ;; + esac log_message "INFO" "${green_fg_strong}Node.js is installed.${reset}" else @@ -662,28 +1742,312 @@ install_nodejs() { fi } +install_yq() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer_core_utilities +} + +install_vs_buildtools() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer_core_utilities +} + +install_cuda_toolkit() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer_core_utilities +} + + +install_tailscale() { + if ! command -v tailscale &> /dev/null; then + log_message "WARN" "${yellow_fg_strong}Tailscale is not installed on this system${reset}" + + # Ask the user if they have a Tailscale account + read -p "Do you have a Tailscale account? [Y/N]: " has_account + if [[ "$has_account" =~ ^[Nn]$ ]]; then + echo -e "${blue_fg_strong}Please create a Tailscale account at https://login.tailscale.com/start${reset}" + xdg-open "https://login.tailscale.com/start" + read -p "Press Enter after you have created an account to continue..." + fi + + # Detect the package manager and install Tailscale + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + log_message "INFO" "Detected apt (Debian/Ubuntu). Installing Tailscale..." + curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null + curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/$(lsb_release -cs).tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list + sudo apt update && sudo apt install -y tailscale + ;; + dnf|yum) + log_message "INFO" "Detected dnf/yum (Red Hat/Fedora). Installing Tailscale..." + sudo dnf config-manager --add-repo https://pkgs.tailscale.com/stable/fedora/tailscale.repo + sudo dnf install -y tailscale + ;; + apk) + log_message "INFO" "Detected apk (Alpine). Installing Tailscale..." + sudo apk add tailscale + ;; + pacman) + log_message "INFO" "Detected pacman (Arch). Installing Tailscale..." + sudo pacman -Sy --noconfirm tailscale + ;; + emerge) + log_message "INFO" "Detected emerge (Gentoo). Installing Tailscale..." + sudo emerge --ask net-vpn/tailscale + ;; + zypper) + log_message "INFO" "Detected zypper (openSUSE). Installing Tailscale..." + sudo zypper addrepo https://pkgs.tailscale.com/stable/opensuse/tailscale.repo + sudo zypper refresh + sudo zypper install -y tailscale + ;; + xbps) + log_message "INFO" "Detected xbps (Void). Installing Tailscale..." + sudo xbps-install -y tailscale + ;; + nix) + log_message "INFO" "Detected nix (NixOS). Installing Tailscale..." + nix-env -iA nixpkgs.tailscale + ;; + guix) + log_message "INFO" "Detected guix (Guix). Installing Tailscale..." + guix package -i tailscale + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + app_installer_core_utilities + ;; + esac + ;; + Darwin) + log_message "INFO" "Detected macOS. Installing Tailscale via Homebrew..." + if ! command -v brew &> /dev/null; then + log_message "ERROR" "${red_fg_strong}Homebrew not installed. Install it first: https://brew.sh/${reset}" + app_installer_core_utilities + fi + brew install tailscale + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_installer_core_utilities + ;; + esac + + # Start and enable Tailscale + if command -v tailscale &> /dev/null; then + log_message "INFO" "${green_fg_strong}Tailscale is installed. Starting Tailscale...${reset}" + sudo tailscale up + if [ $? -eq 0 ]; then + log_message "INFO" "${green_fg_strong}Tailscale is now running.${reset}" + else + log_message "ERROR" "${red_fg_strong}Failed to start Tailscale.${reset}" + fi + else + log_message "ERROR" "${red_fg_strong}Tailscale installation failed.${reset}" + fi + else + log_message "INFO" "${blue_fg_strong}Tailscale is already installed.${reset}" + fi + + read -p "Press Enter to continue..." + app_installer_core_utilities +} + +install_ngrok() { + if ! command -v ngrok &> /dev/null; then + log_message "WARN" "${yellow_fg_strong}ngrok is not installed on this system${reset}" + + # Detect the operating system and architecture + case "$(uname -s)" in + Linux) + case "$(uname -m)" in + x86_64) + arch="amd64" + ;; + armv7l|armv8l|aarch64) + arch="arm64" + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported architecture.${reset}" + exit 1 + ;; + esac + os="linux" + ;; + Darwin) + case "$(uname -m)" in + x86_64) + arch="amd64" + ;; + arm64) + arch="arm64" + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported architecture.${reset}" + app_installer_core_utilities + ;; + esac + os="darwin" + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_installer_core_utilities + ;; + esac + + # Download and install ngrok + log_message "INFO" "Downloading ngrok for ${os}-${arch}..." + download_url="https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-${os}-${arch}.tgz" + temp_dir=$(mktemp -d) + curl -fsSL "$download_url" -o "$temp_dir/ngrok.tgz" + + if [ $? -ne 0 ]; then + log_message "ERROR" "${red_fg_strong}Failed to download ngrok.${reset}" + rm -rf "$temp_dir" + read -p "Press Enter to continue..." + app_installer_core_utilities + fi + + log_message "INFO" "Installing ngrok..." + tar -xzf "$temp_dir/ngrok.tgz" -C "$temp_dir" + sudo mv "$temp_dir/ngrok" /usr/local/bin/ngrok + rm -rf "$temp_dir" + + if command -v ngrok &> /dev/null; then + log_message "INFO" "${green_fg_strong}ngrok is installed.${reset}" + else + log_message "ERROR" "${red_fg_strong}Failed to install ngrok.${reset}" + read -p "Press Enter to continue..." + app_installer_core_utilities + fi + else + log_message "INFO" "${blue_fg_strong}ngrok is already installed.${reset}" + fi + + # Authenticate ngrok if not already authenticated + if [ ! -f "$HOME/.config/ngrok/ngrok.yml" ]; then + log_message "INFO" "Authenticating ngrok..." + echo -e "${blue_fg_strong}Please visit https://dashboard.ngrok.com/signup to create an account if you don't have one.${reset}" + echo -e "${blue_fg_strong}After signing up, go to https://dashboard.ngrok.com/get-started/your-authtoken to get your authtoken.${reset}" + read -p "Enter your ngrok authtoken: " authtoken + ngrok config add-authtoken "$authtoken" + + if [ $? -eq 0 ]; then + log_message "INFO" "${green_fg_strong}ngrok authenticated successfully.${reset}" + else + log_message "ERROR" "${red_fg_strong}Failed to authenticate ngrok.${reset}" + read -p "Press Enter to continue..." + app_installer_core_utilities + fi + else + log_message "INFO" "${blue_fg_strong}ngrok is already authenticated.${reset}" + fi + + read -p "Press Enter to continue..." + app_installer_core_utilities +} + + +app_installer_text_completion() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer +} + +app_installer_voice_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer +} + +app_installer_image_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer +} + +app_installer_core_utilities() { + echo -e "\033]0;STL [APP INSTALLER CORE UTILITIES]\007" + clear + + echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer / Core Utilities |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + + echo " 1. Install 7-Zip" + echo " 2. Install FFmpeg" + echo " 3. Install Node.js" + echo " 4. Install yq" + echo " 5. Install Visual Studio BuildTools" + echo " 6. Install CUDA Toolkit" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Remote Access & Tunneling |${reset}" + echo " 7. Install Tailscale" + echo " 8. Install ngrok" + echo " 9. Install Cloudflare Tunnel" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " app_installer_choice + + case $app_installer_choice in + 1) install_p7zip ;; + 2) install_ffmpeg ;; + 3) install_nodejs ;; + 4) install_yq ;; + 5) install_vs_buildtools ;; + 6) install_cuda_toolkit ;; + 7) install_tailscale ;; + 8) install_ngrok ;; + 9) start_st_remotelink ;; + 0) app_installer ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + app_installer_core_utilities ;; + esac +} + ############################################################ ############## APP INSTALLER - FRONTEND #################### ############################################################ app_installer() { - echo -e "\033]0;SillyTavern [APP INSTALLER]\007" + echo -e "\033]0;STL [APP INSTALLER]\007" clear - echo -e "${blue_fg_strong}/ Home / Toolbox / App Installer${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Install 7-Zip" - echo "2. Install FFmpeg" - echo "3. Install Node.js" - echo "0. Back to Toolbox" + echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Text Completion" + echo " 2. Voice Generation" + echo " 3. Image Generation" + echo " 4. Core Utilities" - read -p "Choose Your Destiny: " app_installer_choice + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" -################# APP INSTALLER - BACKEND ####################### + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " app_installer_choice + +################# APP INSTALLER - BACKEND ################ case $app_installer_choice in - 1) install_p7zip ;; - 2) install_ffmpeg ;; - 3) install_nodejs ;; + 1) app_installer_text_completion ;; + 2) app_installer_voice_generation ;; + 3) app_installer_image_generation ;; + 4) app_installer_core_utilities ;; 0) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." @@ -691,6 +2055,14 @@ app_installer() { esac } + + +######################################################################################## +######################################################################################## +####################### APP UNINSTALLER MENU FUNCTIONS ################################ +######################################################################################## +######################################################################################## + # Function to uninstall Extras uninstall_extras() { echo @@ -756,189 +2128,514 @@ uninstall_st() { if [ "$confirmation" = "Y" ] || [ "$confirmation" = "y" ]; then log_message "INFO" "Removing the SillyTavern directory..." - rm -rf SillyTavern + rm -rf "$st_install_path" log_message "INFO" "${green_fg_strong}SillyTavern uninstalled successfully.${reset}" else echo "Uninstall canceled." fi - pause - app_uninstaller + read -p "Press Enter to continue..." + app_uninstaller_core_utilities } -# Function to uninstall p7zip (7-Zip) uninstall_p7zip() { if command -v 7z &> /dev/null; then - log_message "WARN" "${yellow_fg_strong}p7zip (7-Zip) is installed on this system${reset}" + log_message "INFO" "${blue_fg_strong}Uninstalling p7zip (7-Zip)...${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Uninstalling p7zip (7-Zip) using apt..." - sudo apt-get remove --purge -y p7zip p7zip-full - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Uninstalling p7zip (7-Zip) using yum..." - sudo yum remove -y p7zip p7zip-plugins - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Uninstalling p7zip (7-Zip) using apk..." - sudo apk del p7zip - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Uninstalling p7zip (7-Zip) using pacman..." - sudo pacman -Rns --noconfirm p7zip - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Uninstalling p7zip (7-Zip) using emerge..." - sudo emerge --unmerge p7zip + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + sudo apt remove -y p7zip p7zip-full + ;; + dnf|yum) + sudo $package_manager remove -y p7zip p7zip-plugins + ;; + apk) + sudo apk del p7zip + ;; + pacman) + sudo pacman -Rns --noconfirm p7zip + ;; + emerge) + sudo emerge --unmerge p7zip + ;; + zypper) + sudo zypper remove -y p7zip + ;; + xbps) + sudo xbps-remove -y p7zip + ;; + nix) + nix-env -e p7zip + ;; + guix) + guix package -r p7zip + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + app_uninstaller_core_utilities + ;; + esac + ;; + Darwin) + if command -v brew &> /dev/null; then + brew uninstall p7zip + else + log_message "ERROR" "${red_fg_strong}Homebrew not installed.${reset}" + app_uninstaller_core_utilities + fi + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_uninstaller_core_utilities + ;; + esac + + if ! command -v 7z &> /dev/null; then + log_message "INFO" "${green_fg_strong}p7zip (7-Zip) has been successfully uninstalled.${reset}" else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 + log_message "ERROR" "${red_fg_strong}Failed to uninstall p7zip (7-Zip).${reset}" + app_uninstaller_core_utilities fi - - log_message "INFO" "${green_fg_strong}p7zip (7-Zip) is uninstalled.${reset}" else log_message "INFO" "${blue_fg_strong}p7zip (7-Zip) is not installed.${reset}" fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities } -# Function to uninstall FFmpeg uninstall_ffmpeg() { if command -v ffmpeg &> /dev/null; then - log_message "WARN" "${yellow_fg_strong}FFmpeg is installed on this system${reset}" + log_message "INFO" "${blue_fg_strong}Uninstalling FFmpeg...${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Uninstalling FFmpeg using apt..." - sudo apt-get remove --purge -y ffmpeg - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Uninstalling FFmpeg using yum..." - sudo yum remove -y ffmpeg - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Uninstalling FFmpeg using apk..." - sudo apk del ffmpeg - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Uninstalling FFmpeg using pacman..." - sudo pacman -Rns --noconfirm ffmpeg - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Uninstalling FFmpeg using emerge..." - sudo emerge --unmerge ffmpeg + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + sudo apt remove -y ffmpeg + ;; + dnf|yum) + sudo $package_manager remove -y ffmpeg + ;; + apk) + sudo apk del ffmpeg + ;; + pacman) + sudo pacman -Rns --noconfirm ffmpeg + ;; + emerge) + sudo emerge --unmerge ffmpeg + ;; + zypper) + sudo zypper remove -y ffmpeg + ;; + xbps) + sudo xbps-remove -y ffmpeg + ;; + nix) + nix-env -e ffmpeg + ;; + guix) + guix package -r ffmpeg + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + app_uninstaller_core_utilities + ;; + esac + ;; + Darwin) + if command -v brew &> /dev/null; then + brew uninstall ffmpeg + else + log_message "ERROR" "${red_fg_strong}Homebrew not installed.${reset}" + app_uninstaller_core_utilities + fi + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_uninstaller_core_utilities + ;; + esac + + if ! command -v ffmpeg &> /dev/null; then + log_message "INFO" "${green_fg_strong}FFmpeg has been successfully uninstalled.${reset}" else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 + log_message "ERROR" "${red_fg_strong}Failed to uninstall FFmpeg.${reset}" + app_uninstaller_core_utilities fi - - log_message "INFO" "${green_fg_strong}FFmpeg is uninstalled.${reset}" else log_message "INFO" "${blue_fg_strong}FFmpeg is not installed.${reset}" fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities } - -# Function to uninstall Node.js and npm uninstall_nodejs() { + echo -e "\033]0;STL [UNINSTALL NODEJS]\007" if command -v node &> /dev/null; then - log_message "WARN" "${yellow_fg_strong}Node.js is installed on this system${reset}" + log_message "INFO" "${blue_fg_strong}Uninstalling Node.js...${reset}" + rm -rf /usr/local/bin/npm + rm -rf /usr/local/share/man/man1/node* + rm -rf /usr/local/lib/dtrace/node.d + rm -rf ~/.npm + rm -rf ~/.node-gyp + rm -rf /opt/local/bin/node + rm -rf /opt/local/include/node + rm -rf /opt/local/lib/node_modules + rm -rf /usr/local/lib/node* + rm -rf /usr/local/include/node* + rm -rf /usr/local/bin/node* + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + sudo apt remove -y nodejs npm + ;; + dnf|yum) + sudo $package_manager remove -y nodejs npm + ;; + apk) + sudo apk del nodejs npm + ;; + pacman) + sudo pacman -Rns --noconfirm nodejs npm + ;; + emerge) + sudo emerge --unmerge nodejs + ;; + zypper) + sudo zypper remove -y nodejs npm + ;; + xbps) + sudo xbps-remove -y nodejs npm + ;; + nix) + nix-env -e nodejs + ;; + guix) + guix package -r node + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + exit 1 + ;; + esac + ;; + Darwin) + if command -v brew &> /dev/null; then + brew uninstall node + else + log_message "ERROR" "${red_fg_strong}Homebrew not installed.${reset}" + exit 1 + fi + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + exit 1 + ;; + esac - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Uninstalling Node.js using apt..." - sudo apt-get remove --purge -y nodejs npm - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Uninstalling Node.js using yum..." - sudo yum remove -y nodejs npm - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Uninstalling Node.js using apk..." - sudo apk del nodejs npm - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Uninstalling Node.js using pacman..." - sudo pacman -Rns --noconfirm nodejs npm - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Uninstalling Node.js using emerge..." - sudo emerge --unmerge nodejs - else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 + if ! command -v node &> /dev/null; then + log_message "INFO" "${green_fg_strong}Node.js successfully uninstalled.${reset}" fi - - log_message "INFO" "${green_fg_strong}Node.js and npm are uninstalled.${reset}" else log_message "INFO" "${blue_fg_strong}Node.js is not installed.${reset}" fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities } -# Function to uninstall Git + uninstall_git() { if command -v git &> /dev/null; then - log_message "WARN" "${yellow_fg_strong}Git is installed on this system${reset}" + log_message "INFO" "${blue_fg_strong}Uninstalling Git...${reset}" - if command -v apt-get &>/dev/null; then - # Debian/Ubuntu-based system - log_message "INFO" "Uninstalling Git using apt..." - sudo apt-get remove --purge -y git - elif command -v yum &>/dev/null; then - # Red Hat/Fedora-based system - log_message "INFO" "Uninstalling Git using yum..." - sudo yum remove -y git - elif command -v apk &>/dev/null; then - # Alpine Linux-based system - log_message "INFO" "Uninstalling Git using apk..." - sudo apk del git - elif command -v pacman &>/dev/null; then - # Arch Linux-based system - log_message "INFO" "Uninstalling Git using pacman..." - sudo pacman -Rns --noconfirm git - elif command -v emerge &>/dev/null; then - # Gentoo Linux-based system - log_message "INFO" "Uninstalling Git using emerge..." - sudo emerge --unmerge dev-vcs/git + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + sudo apt remove -y git + ;; + dnf|yum) + sudo $package_manager remove -y git + ;; + apk) + sudo apk del git + ;; + pacman) + sudo pacman -Rns --noconfirm git + ;; + emerge) + sudo emerge --unmerge dev-vcs/git + ;; + zypper) + sudo zypper remove -y git + ;; + xbps) + sudo xbps-remove -y git + ;; + nix) + nix-env -e git + ;; + guix) + guix package -r git + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + app_uninstaller_core_utilities + ;; + esac + ;; + Darwin) + if command -v brew &> /dev/null; then + brew uninstall git + else + log_message "ERROR" "${red_fg_strong}Homebrew not installed.${reset}" + app_uninstaller_core_utilities + fi + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_uninstaller_core_utilities + ;; + esac + + if ! command -v git &> /dev/null; then + log_message "INFO" "${green_fg_strong}Git has been successfully uninstalled.${reset}" else - log_message "ERROR" "${red_fg_strong}Unsupported Linux distribution.${reset}" - exit 1 + log_message "ERROR" "${red_fg_strong}Failed to uninstall Git.${reset}" + app_uninstaller_core_utilities fi - - log_message "INFO" "${green_fg_strong}Git is uninstalled.${reset}" else log_message "INFO" "${blue_fg_strong}Git is not installed.${reset}" fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities } + +uninstall_tailscale() { + if command -v tailscale &> /dev/null; then + log_message "INFO" "${blue_fg_strong}Uninstalling Tailscale...${reset}" + + # Stop Tailscale service + if systemctl is-active --quiet tailscaled; then + log_message "INFO" "Stopping Tailscale service..." + sudo systemctl stop tailscaled + fi + + # Disable Tailscale service + if systemctl is-enabled --quiet tailscaled; then + log_message "INFO" "Disabling Tailscale service..." + sudo systemctl disable tailscaled + fi + + # Remove Tailscale binary and configuration files + case "$(uname -s)" in + Linux) + package_manager=$(detect_package_manager) + case "$package_manager" in + apt) + sudo apt remove -y tailscale + ;; + dnf|yum) + sudo $package_manager remove -y tailscale + ;; + apk) + sudo apk del tailscale + ;; + pacman) + sudo pacman -R --noconfirm tailscale + ;; + emerge) + sudo emerge --ask --depclean net-vpn/tailscale + ;; + zypper) + sudo zypper remove -y tailscale + ;; + xbps) + sudo xbps-remove -y tailscale + ;; + nix) + nix-env -e tailscale + ;; + guix) + guix package -r tailscale + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported package manager or distribution.${reset}" + app_uninstaller_core_utilities + ;; + esac + ;; + Darwin) + if command -v brew &> /dev/null; then + brew uninstall tailscale + else + log_message "ERROR" "${red_fg_strong}Homebrew not installed.${reset}" + app_uninstaller_core_utilities + fi + ;; + *) + log_message "ERROR" "${red_fg_strong}Unsupported operating system.${reset}" + app_uninstaller_core_utilities + ;; + esac + + # Remove Tailscale configuration files + if [ -d "/var/lib/tailscale" ]; then + log_message "INFO" "Removing Tailscale configuration files..." + sudo rm -rf /var/lib/tailscale + fi + + if ! command -v tailscale &> /dev/null; then + log_message "INFO" "${green_fg_strong}Tailscale has been successfully uninstalled.${reset}" + else + log_message "ERROR" "${red_fg_strong}Failed to uninstall Tailscale.${reset}" + app_uninstaller_core_utilities + fi + else + log_message "INFO" "${blue_fg_strong}Tailscale is not installed.${reset}" + fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities +} + + +uninstall_ngrok() { + if command -v ngrok &> /dev/null; then + log_message "INFO" "${blue_fg_strong}Uninstalling ngrok...${reset}" + + # Remove the ngrok binary + sudo rm -f /usr/local/bin/ngrok + + # Remove ngrok configuration files + if [ -d "$HOME/.config/ngrok" ]; then + log_message "INFO" "Removing ngrok configuration files..." + rm -rf "$HOME/.config/ngrok" + fi + + if ! command -v ngrok &> /dev/null; then + log_message "INFO" "${green_fg_strong}ngrok has been successfully uninstalled.${reset}" + else + log_message "ERROR" "${red_fg_strong}Failed to uninstall ngrok.${reset}" + app_uninstaller_core_utilities + fi + else + log_message "INFO" "${blue_fg_strong}ngrok is not installed.${reset}" + fi + + read -p "Press Enter to continue..." + app_uninstaller_core_utilities +} + +app_uninstaller_text_completion() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer +} + +app_uninstaller_voice_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_installer +} + +app_uninstaller_image_generation() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + app_uninstaller +} + +app_uninstaller_core_utilities() { + echo -e "\033]0;STL [APP UNINSTALLER CORE UTILITIES]\007" + clear + + echo -e "${blue_fg_strong}| > / Home / Toolbox / App Uninstaller / Core Utilities |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + + echo " 1. UNINSTALL Extras" + echo " 2. UNINSTALL SillyTavern" + echo " 3. UNINSTALL 7-Zip" + echo " 4. UNINSTALL FFmpeg" + echo " 5. UNINSTALL Node.js" + echo " 6. UNINSTALL yq" + echo " 7. UNINSTALL Visual Studio BuildTools" + echo " 8. UNINSTALL CUDA Toolkit" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Remote Access & Tunneling |${reset}" + echo " 9. UNINSTALL Tailscale" + echo " 10. UNINSTALL ngrok" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " app_uninstaller_choice + + case $app_uninstaller_choice in + 1) uninstall_extras ;; + 2) uninstall_st ;; + 3) uninstall_p7zip ;; + 4) uninstall_ffmpeg ;; + 5) uninstall_nodejs ;; + 6) uninstall_yq ;; + 7) uninstall_vs_buildtools ;; + 8) uninstall_cuda_toolkit ;; + 9) uninstall_tailscale ;; + 10) uninstall_ngrok ;; + + 0) app_uninstaller ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + app_uninstaller_core_utilities ;; + esac +} + + ############################################################ ############## APP UNINSTALLER - FRONTEND ################## ############################################################ app_uninstaller() { - echo -e "\033]0;SillyTavern [APP UNINSTALLER]\007" + echo -e "\033]0;STL [APP UNINSTALLER]\007" clear - echo -e "${blue_fg_strong}/ Home / Toolbox / App Uninstaller${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. UNINSTALL Extras" - echo "2. UNINSTALL XTTS" - echo "3. UNINSTALL SillyTavern" - echo "4. UNINSTALL 7-Zip" - echo "5. UNINSTALL FFmpeg" - echo "6. UNINSTALL Node.js" - echo "7. UNINSTALL git" - echo "0. Back to Toolbox" + echo -e "${blue_fg_strong}| > / Home / Toolbox / App Uninstaller |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Text Completion" + echo " 2. Voice Generation" + echo " 3. Image Generation" + echo " 4. Core Utilities" - read -p "Choose Your Destiny: " app_uninstaller_choice + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" -################# APP UNINSTALLER - BACKEND ####################### + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Choose Your Destiny: " app_uninstaller_choice + +################# APP UNINSTALLER - BACKEND ################ case $app_uninstaller_choice in - 1) uninstall_extras ;; - 2) uninstall_xtts ;; - 3) uninstall_st ;; - 4) uninstall_p7zip ;; - 5) uninstall_ffmpeg ;; - 6) uninstall_nodejs ;; - 7) uninstall_git ;; + 1) app_uninstaller_text_completion ;; + 2) app_uninstaller_voice_generation ;; + 3) app_uninstaller_image_generation ;; + 4) app_uninstaller_core_utilities ;; 0) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." @@ -946,339 +2643,41 @@ app_uninstaller() { esac } - -# Function to print module options with color based on their status -printModule() { - if [ "$2" == "true" ]; then - echo -e "\e[32;1m$1 [Enabled]\e[0m" - else - echo -e "\e[31;1m$1 [Disabled]\e[0m" - fi -} - -# Function to edit extras modules -edit_extras_modules() { - echo -e "\033]0;SillyTavern [EDIT-MODULES]\007" - clear - echo -e "${blue_fg_strong}/ Home / Toolbox / Editor / Edit Extras Modules${reset}" - echo "-------------------------------------" - echo "Choose extras modules to enable or disable (e.g., \"1 2 4\" to enable Cuda, RVC, and Caption)" - - # Display module options with colors based on their status - printModule "1. Cuda (--gpu 0 --cuda --cuda-device=0)" "$cuda_trigger" - printModule "2. RVC (--enable-modules=rvc --rvc-save-file --max-content-length=1000)" "$rvc_trigger" - printModule "3. talkinghead (--enable-modules=talkinghead)" "$talkinghead_trigger" - printModule "4. caption (--enable-modules=caption)" "$caption_trigger" - printModule "5. summarize (--enable-modules=summarize)" "$summarize_trigger" - printModule "6. listen (--listen)" "$listen_trigger" - printModule "7. Edge TTS (--enable-modules=edge-tts)" "$edge_tts_trigger" - echo "0. Back to Toolbox" - - set "python_command=" - - read -p "Choose modules to enable/disable (1-6): " module_choices - - # Handle the user's module choices and construct the Python command - for i in $module_choices; do - case $i in - 1) [ "$cuda_trigger" == "true" ] && cuda_trigger=false || cuda_trigger=true ;; - 2) [ "$rvc_trigger" == "true" ] && rvc_trigger=false || rvc_trigger=true ;; - 3) [ "$talkinghead_trigger" == "true" ] && talkinghead_trigger=false || talkinghead_trigger=true ;; - 4) [ "$caption_trigger" == "true" ] && caption_trigger=false || caption_trigger=true ;; - 5) [ "$summarize_trigger" == "true" ] && summarize_trigger=false || summarize_trigger=true ;; - 6) [ "$listen_trigger" == "true" ] && listen_trigger=false || listen_trigger=true ;; - 7) [ "$edge_tts_trigger" == "true" ] && edge_tts_trigger=false || edge_tts_trigger=true ;; - 0) toolbox ;; - esac - done - - # Save the module flags to modules.txt - modules_file="$(dirname "$0")/modules.txt" - echo "cuda_trigger=$cuda_trigger" > "$modules_file" - echo "rvc_trigger=$rvc_trigger" >> "$modules_file" - echo "talkinghead_trigger=$talkinghead_trigger" >> "$modules_file" - echo "caption_trigger=$caption_trigger" >> "$modules_file" - echo "summarize_trigger=$summarize_trigger" >> "$modules_file" - echo "listen_trigger=$listen_trigger" >> "$modules_file" - echo "edge_tts_trigger=$edge_tts_trigger" >> "$modules_file" - - # Compile the Python command - python_command="python server.py" - [ "$listen_trigger" == "true" ] && python_command+=" --listen" - [ "$cuda_trigger" == "true" ] && python_command+=" --gpu 0 --cuda --cuda-device=0 " - [ "$rvc_trigger" == "true" ] && python_command+=" --rvc-save-file --max-content-length=1000" - modules_enable="" - [ "$talkinghead_trigger" == "true" ] && modules_enable+="talkinghead," - [ "$caption_trigger" == "true" ] && modules_enable+="caption," - [ "$summarize_trigger" == "true" ] && modules_enable+="summarize," - [ "$edge_tts_trigger" == "true" ] && modules_enable+="edge-tts," - - # Remove the last comma from modules_enable - modules_enable="${modules_enable%,}" - - # Save the constructed Python command to modules.txt for testing - echo "start_command=$python_command --enable-modules=$modules_enable" >> "$modules_file" - edit_extras_modules -} - -# Function to edit XTTS modules -edit_xtts_modules() { - echo -e "\033]0;SillyTavern [EDIT-XTTS-MODULES]\007" - clear - echo -e "${blue_fg_strong}/ Home / Toolbox / Editor / Edit XTTS Modules${reset}" - echo "-------------------------------------" - echo "Choose XTTS modules to enable or disable (e.g., "1 2 4" to enable Cuda, hs, and cache)" - - # Display module options with colors based on their status - printModule "1. cuda (--device cuda)" "$xtts_cuda_trigger" - printModule "2. hs (-hs 0.0.0.0)" "$xtts_hs_trigger" - printModule "3. deepspeed (--deepspeed)" "$xtts_deepspeed_trigger" - printModule "4. cache (--use-cache)" "$xtts_cache_trigger" - printModule "5. listen (--listen)" "$xtts_listen_trigger" - printModule "6. model (--model-source local)" "$xtts_model_trigger" - echo "0. Back to Editor"s - - set "python_command=" - - read -p "Choose modules to enable/disable (1-6): " module_choices - - # Handle the user's module choices and construct the Python command - for i in $module_choices; do - case $i in - 1) [ "$xtts_cuda_trigger" == "true" ] && xtts_cuda_trigger=false || xtts_cuda_trigger=true ;; - 2) [ "$xtts_hs_trigger" == "true" ] && xtts_hs_trigger=false || xtts_hs_trigger=true ;; - 3) [ "$xtts_deepspeed_trigger" == "true" ] && xtts_deepspeed_trigger=false || xtts_deepspeed_trigger=true ;; - 4) [ "$xtts_cache_trigger" == "true" ] && xtts_cache_trigger=false || xtts_cache_trigger=true ;; - 5) [ "$xtts_listen_trigger" == "true" ] && xtts_listen_trigger=false || xtts_listen_trigger=true ;; - 6) [ "$xtts_model_trigger" == "true" ] && xtts_model_trigger=false || xtts_model_trigger=true ;; - 0) editor ;; - esac - done - - # Save the module flags to modules-xtts.txt - modules_file="$(dirname "$0")/modules-xtts.txt" - echo "xtts_cuda_trigger=$xtts_cuda_trigger" > "$modules_file" - echo "xtts_hs_trigger=$xtts_hs_trigger" >> "$modules_file" - echo "xtts_deepspeed_trigger=$xtts_deepspeed_trigger" >> "$modules_file" - echo "xtts_cache_trigger=$xtts_cache_trigger" >> "$modules_file" - echo "xtts_listen_trigger=$xtts_listen_trigger" >> "$modules_file" - echo "xtts_model_trigger=$xtts_model_trigger" >> "$modules_file" - - # Compile the Python command - python_command="python server.py" - [ "$xtts_cuda_trigger" == "true" ] && python_command+=" --device cuda" - [ "$xtts_hs_trigger" == "true" ] && python_command+=" -hs 0.0.0.0" - [ "$xtts_deepspeed_trigger" == "true" ] && python_command+=" --deepspeed" - [ "$xtts_cache_trigger" == "true" ] && python_command+=" --use-cache" - [ "$xtts_listen_trigger" == "true" ] && python_command+=" --listen" - [ "$xtts_model_trigger" == "true" ] && python_command+=" --model-source local" - - # Save the constructed Python command to modules.txt for testing - echo "start_command=$python_command" >> "$modules_file" - edit_xtts_modules -} - - -# Function to edit environment variables -edit_environment_var() { - # Open the environment variables file for editing - if [ -f ~/.bashrc ]; then - # Use your preferred text editor (e.g., nano, vim, or gedit) - nano ~/.bashrc - else - echo "Environment file not found. Create or specify the correct file path." - fi - - # Provide instructions to the user - echo "Edit your environment variables. Save and exit the editor when done." - - # Optionally, ask the user to reload the environment - read -p "Do you want to reload the environment? (Y/N): " reload - if [ "$reload" = "Y" ] || [ "$reload" = "y" ]; then - source ~/.bashrc # Reload the environment (may vary based on your shell) - echo "Environment reloaded." - fi -} - - -edit_st_config() { - # Check if nano is available - if ! command -v nano &>/dev/null; then - echo "Error: Nano is not installed. Please install Nano to edit config.yaml" - exit 1 - fi - # Open config.yaml file in nano - nano "$(dirname "$0")/SillyTavern/config.yaml" -} - -############################################################ -############## EDITOR - FRONTEND ########################### -############################################################ -editor() { - echo -e "\033]0;SillyTavern [EDITOR]\007" - clear - echo -e "${blue_fg_strong}/ Home / Toolbox / Editor${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Edit Extras Modules" - echo "2. Edit XTTS Modules" - echo "3. Edit Environment Variables" - echo "4. Edit SillyTavern config.yaml" - echo "0. Back to Toolbox" - - read -p "Choose Your Destiny: " editor_choice - -################# EDITOR - BACKEND ######################### - case $editor_choice in - 1) edit_extras_modules ;; - 2) edit_xtts_modules ;; - 3) edit_environment_var ;; - 4) edit_st_config ;; - 0) toolbox ;; - *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" - read -p "Press Enter to continue..." - editor ;; - esac -} - - -# Function to remove node modules folder -remove_node_modules() { - log_message "INFO" "Removing node_modules folder..." - cd "$(dirname "$0")./SillyTavern" - rm -rf node_modules - npm cache clean --force - log_message "INFO" "node_modules successfully removed." - read -p "Press Enter to continue..." - troubleshooting -} - -unresolved_unmerged() { - log_message "INFO" "Trying to resolve unresolved conflicts in the working directory or unmerged files..." - cd "$(dirname "$0")./SillyTavern" - git merge --abort - git reset --hard - git pull --rebase --autostash - read -p "Press Enter to continue..." - troubleshooting -} - -export_system_info() { - log_message "INFO" "Exporting system information..." - lshw > "$(dirname "$0")/system_info.txt" - log_message "INFO" "You can find the system_info.txt at: $(dirname "$0")/system_info.txt" - read -p "Press Enter to continue..." - troubleshooting -} - -# Function to find and display the application using the specified port -find_app_port() { - clear - read -p "Insert port number: " port - - # Check if the input is a number - if ! [[ "$port" =~ ^[0-9]+$ ]]; then - log_message "ERROR" "Invalid input: Not a number." - read -p "Press Enter to continue..." - find_app_port - fi - - # Check if the port is within range - if (( port > 65535 )); then - log_message "ERROR" "Port out of range. There are only 65,535 possible port numbers." - echo "[0-1023]: These ports are reserved for system services or commonly used protocols." - echo "[1024-49151]: These ports can be used by user processes or applications." - echo "[49152-65535]: These ports are available for use by any application or service on the system." - read -p "Press Enter to continue..." - find_app_port - fi - - log_message "INFO" "Searching for application using port: $port..." - pid=$(netstat -tuln | awk '{print $4}' | grep ":$port" | awk -F'/' '{print $NF}') - - if [[ -n "$pid" ]]; then - app_name=$(ps -p $pid -o comm=) - echo -e "Application Name: \e[36;1m$app_name\e[0m" - echo -e "PID of Port $port: \e[36;1m$pid\e[0m" - else - log_message "WARN" "Port: $port not found." - read -p "Press Enter to continue..." - find_app_port - fi - - read -p "Press Enter to continue..." - troubleshooting -} - -onboarding_flow() { - read -p "Enter new value for Onboarding Flow (true/false): " onboarding_flow_value - if [[ "$onboarding_flow_value" != "true" && "$onboarding_flow_value" != "false" ]]; then - log_message "WARN" "Invalid input. Please enter 'true' or 'false'." - read -p "Press Enter to continue..." - onboarding_flow - fi - sed -i "s/\"firstRun\": .*/\"firstRun\": $onboarding_flow_value,/" "$PWD/SillyTavern/public/settings.json" - log_message "INFO" "Value of 'firstRun' in settings.json has been updated to $onboarding_flow_value." - read -p "Press Enter to continue..." - troubleshooting -} - -############################################################ -############## TROUBLESHOOTING - FRONTEND ################## -############################################################ -troubleshooting() { - echo -e "\033]0;SillyTavern [TROUBLESHOOTING]\007" - clear - echo -e "${blue_fg_strong}/ Home / Toolbox / Troubleshooting${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. Remove node_modules folder" - echo "2. Fix unresolved conflicts or unmerged files [SillyTavern]" - echo "3. Export system info" - echo "4. Find what app is using port" - echo "5. Set Onboarding Flow" - echo "0. Back to Toolbox" - - read -p "Choose Your Destiny: " troubleshooting_choice - -################# TROUBLESHOOTING - BACKEND ################ - case $troubleshooting_choice in - 1) remove_node_modules ;; - 2) unresolved_unmerged ;; - 3) export_system_info ;; - 4) find_app_port ;; - 5) onboarding_flow ;; - 0) toolbox ;; - *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" - read -p "Press Enter to continue..." - troubleshooting ;; - esac -} - - ############################################################ ################# TOOLBOX - FRONTEND ####################### ############################################################ toolbox() { - echo -e "\033]0;SillyTavern [TOOLBOX]\007" + echo -e "\033]0;STL [TOOLBOX]\007" clear - echo -e "${blue_fg_strong}/ Home / Toolbox${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. App Installer" - echo "2. App Uninstaller" - echo "3. Editor" - echo "4. Troubleshooting" - echo "0. Back to Home" + echo -e "${blue_fg_strong}| > / Home / Toolbox |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. App Launcher" + echo " 2. App Installer" + echo " 3. App Uninstaller" + echo " 4. Editor" + echo " 5. Backup" + echo " 6. Switch Branch" + echo " 7. Reset Custom Shortcut" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Back" - read -p "Choose Your Destiny: " toolbox_choice + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + + read -p " Choose Your Destiny: " toolbox_choice ################# TOOLBOX - BACKEND ####################### case $toolbox_choice in - 1) app_installer ;; - 2) app_uninstaller ;; - 3) editor ;; - 4) troubleshooting ;; + 1) app_launcher ;; + 2) app_installer ;; + 3) app_uninstaller ;; + 4) editor ;; + 5) backup ;; + 6) switch_branch ;; + 7) reset_custom_shortcut ;; 0) home ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." @@ -1287,121 +2686,638 @@ toolbox() { } -issue_report() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose - else - xdg-open https://github.com/SillyTavern/SillyTavern-Launcher/issues/new/choose - fi - fi - read -p "Press Enter to continue..." - support +######################################################################################## +######################################################################################## +####################### STARTUP CHECK FUNCTIONS ####################################### +######################################################################################## +######################################################################################## + +# Function to detect package manager +detect_package_manager() { + local package_manager + + case "$(true; command -v apt dnf yum apk pacman emerge zypper xbps-install guix nix-env 2>/dev/null | head -n1)" in + *apt) package_manager="apt" ;; + *dnf) package_manager="dnf" ;; + *yum) package_manager="yum" ;; + *apk) package_manager="apk" ;; + *pacman) package_manager="pacman" ;; + *emerge) package_manager="emerge" ;; + *zypper) package_manager="zypper" ;; + *xbps-install) package_manager="xbps" ;; + *guix) package_manager="guix" ;; + *nix-env) package_manager="nix" ;; + *) + if [ -f /etc/os-release ]; then + os_id=$(grep -E '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"') + case "$os_id" in + almalinux|centos_stream|ol|rhel|rocky|fedora|fedoraremixforwsl|nobara) + package_manager="yum" ;; + alpine|wolfi) + package_manager="apk" ;; + arch|arch32|archcraft|arcolinux|arkane|artix|aurora|bazzite|blackarch|blendos|bluefin|bodhi|cachyos|chimera|chimeraos|endeavouros|garuda|hyperbola|kaos|manjaro|manjaro-arm|rebornos|steamos|void) + package_manager="pacman" ;; + debian|devuan|elementary|kali|linuxmint|parrot|pika|pisilinux|pop|pureos|raspbian|tails|ubuntu|ubuntu_kylin|vanillaos|zorin) + package_manager="apt" ;; + opensuse-leap|opensuse-tumbleweed|sled|sles) + package_manager="zypper" ;; + gentoo|funtoo) + package_manager="emerge" ;; + nixos) + package_manager="nix" ;; + guix) + package_manager="guix" ;; + clear-linux-os|miraclelinux|photon|solus|tencentos|tinycore|trisquel|ultramarine) + package_manager="unknown" ;; # Custom handling needed + *) + package_manager="unknown" ;; + esac + else + package_manager="unknown" + fi + ;; + esac + + echo "$package_manager" } -documentation() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://docs.sillytavern.app/ - else - xdg-open https://docs.sillytavern.app/ - fi +# Function to create the logs folder if it doesn't exist +create_logs_folder() { + if [ ! -d "$log_dir" ]; then + mkdir -p "$log_dir" + log_message "INFO" "Created logs directory: $log_dir" fi - read -p "Press Enter to continue..." - support } -discord() { - if [ "$EUID" -eq 0 ]; then - log_message "ERROR" "${red_fg_strong}Cannot run xdg-open as root. Please run the script without root permission.${reset}" - else - if [ "$(uname -s)" == "Darwin" ]; then - open https://discord.gg/sillytavern - else - xdg-open https://discord.gg/sillytavern - fi +# Function to check if the folder path has no spaces +check_path_spaces() { + if [[ "$PWD" =~ [[:space:]] ]]; then + log_message "ERROR" "${red_fg_strong}Path cannot have spaces! Please remove them or replace with: - ${reset}" + log_message "ERROR" "Folders containing spaces make the launcher unstable." + log_message "ERROR" "Path: ${red_fg_strong}$PWD${reset}" + exit 1 + fi +} + +# Function to check if the folder path has no special characters +check_path_special_chars() { + if [[ "$PWD" =~ [\!\#\$\%\&\*\+\,\;\<\=\>\?\@\[\]\^\`\{\|\}\~] ]]; then + log_message "ERROR" "${red_fg_strong}Path cannot have special characters! Please remove them.${reset}" + log_message "ERROR" "Folders containing special characters make the launcher unstable." + log_message "ERROR" "Path: ${red_fg_strong}$PWD${reset}" + exit 1 fi - read -p "Press Enter to continue..." - support } -############################################################ -############## SUPPORT - FRONTEND ########################## -############################################################ -support() { - echo -e "\033]0;SillyTavern [SUPPORT]\007" +# Function to check for updates in the launcher +check_launcher_updates() { + log_message "INFO" "Checking for updates..." + git fetch origin + current_branch=$(git branch --show-current) + if [ "$(git rev-list HEAD..origin/$current_branch)" ]; then + log_message "INFO" "${cyan_fg_strong}New update for SillyTavern-Launcher is available!${reset}" + read -p "Update now? [Y/n]: " update_choice + update_choice=${update_choice:-Y} + if [[ "$update_choice" =~ ^[Yy]$ ]]; then + log_message "INFO" "Updating the repository..." + git pull + log_message "INFO" "${green_fg_strong}SillyTavern-Launcher updated successfully. Restarting launcher...${reset}" + sleep 10 + exec ./launcher.sh + exit + fi + else + log_message "INFO" "${green_fg_strong}SillyTavern-Launcher is up to date.${reset}" + fi +} + +# Function to create necessary directories +create_directories() { + if [ ! -d "$bin_dir" ]; then + mkdir -p "$bin_dir" + log_message "INFO" "Created folder: $bin_dir" + fi + + if [ ! -d "$functions_dir" ]; then + mkdir -p "$functions_dir" + log_message "INFO" "Created folder: $functions_dir" + fi + + if [ ! -d "$log_dir" ]; then + mkdir -p "$log_dir" + log_message "INFO" "Created folder: $log_dir" + fi +} + +# Function to create empty module files if they don't exist +create_module_files() { + modules=("extras" "xtts" "sdwebui" "ooba" "tabbyapi") + for module in "${modules[@]}"; do + module_path="$bin_dir/settings/modules-$module.txt" + if [ ! -f "$module_path" ]; then + touch "$module_path" + log_message "INFO" "Created text file: modules-$module.txt" + fi + done +} + + +# Function to check if Miniconda3 is installed +check_miniconda() { + if ! command -v conda &> /dev/null; then + log_message "WARN" "${yellow_fg_strong}Miniconda3 is not installed on this system.${reset}" + log_message "INFO" "Please install Miniconda3 manually from https://docs.conda.io/en/latest/miniconda.html" + else + log_message "INFO" "${blue_fg_strong}Miniconda3 is already installed.${reset}" + fi +} + +# Function to check if SillyTavern folder exists +check_sillytavern_folder() { + if [ ! -d "$st_install_path" ]; then + log_message "ERROR" "${red_fg_strong}SillyTavern not found in: $st_install_path${reset}" + read -p "Press Enter to run the install.sh script" + ./install.sh + fi +} + +# Function to check for updates in SillyTavern +check_sillytavern_updates() { + cd "$st_install_path" || { log_message "ERROR" "${red_fg_strong}Failed to change directory to SillyTavern.${reset}"; exit 1; } + log_message "INFO" "Checking for SillyTavern updates..." + git fetch origin + if [ "$(git rev-list HEAD..origin/$(git branch --show-current))" ]; then + log_message "INFO" "${cyan_fg_strong}New update for SillyTavern is available!${reset}" + read -p "Update now? [Y/n]: " update_choice + update_choice=${update_choice:-Y} + if [[ "$update_choice" =~ ^[Yy]$ ]]; then + log_message "INFO" "Updating SillyTavern..." + git pull + log_message "INFO" "${green_fg_strong}SillyTavern updated successfully.${reset}" + fi + else + log_message "INFO" "${green_fg_strong}SillyTavern is up to date.${reset}" + fi +} + + +######################################################################################## +######################################################################################## +####################### DISPLAY STATUS FUNCTIONS ###################################### +######################################################################################## +######################################################################################## + +# Function to get the current Git branch +get_current_branch() { + current_st_branch=$(git -C "$st_install_path" branch --show-current) + +} + +# Function to manage the GPU info counter +manage_gpu_counter() { + counter_file="$log_dir/gpu_counter.txt" + if [ -f "$counter_file" ]; then + counter=$(cat "$counter_file") + counter=$((counter + 1)) + else + counter=1 + fi + + if [ "$counter" -ge 10 ]; then + counter=0 + rm -f "$log_dir/gpu_info_output.txt" + fi + + echo "$counter" > "$counter_file" +} + +# Function to detect GPU info +detect_gpu_info() { + if [ ! -f "$log_dir/gpu_info_output.txt" ]; then + "$troubleshooting_dir/gpu_info.sh" > "$log_dir/gpu_info_output.txt" + fi + + if [ -f "$log_dir/gpu_info_output.txt" ]; then + gpuInfo=$(cat "$log_dir/gpu_info_output.txt") + else + gpuInfo="GPU Info not found" + fi +} + +# Function to read Tailscale status +read_tailscale_status() { + if [ -f "$log_dir/tailscale_status.txt" ]; then + count=0 + while IFS= read -r line; do + count=$((count + 1)) + case $count in + 1) ip4="$line" ;; + 2) hostName="$line" ;; + 3) dnsName="$line" ;; + esac + done < "$log_dir/tailscale_status.txt" + + # Remove trailing period from dnsName if it exists + if [[ "$dnsName" == *. ]]; then + dnsName="${dnsName%.}" + fi + fi +} + +# Function to get SillyTavern version from package.json +get_sillytavern_version() { + if [ -f "$st_package_json_path" ]; then + st_version=$(grep -oP '"version": "\K[^"]+' "$st_package_json_path") + else + st_version="${red_fg_strong}[ERROR] Cannot get ST version because package.json file not found in $st_install_path${reset}" + fi +} + +# Function to display version and compatibility status +display_version_status() { + echo -e "${yellow_fg_strong} ______________________________________________________________${reset}" + echo -e "${yellow_fg_strong}| Version & Compatibility Status: |${reset}" + echo -e " SillyTavern - Branch: ${cyan_fg_strong}$current_st_branch ${reset}| Status: ${cyan_fg_strong}$update_status_st${reset}" + echo -e " SillyTavern: ${cyan_fg_strong}$st_version${reset}" + echo -e " STL: ${cyan_fg_strong}$stl_version${reset}" + echo -e " Node.js: ${cyan_fg_strong}$node_version${reset}" + + if [ -n "$ip4" ]; then + echo -e " Tailscale URL - IP4: ${cyan_fg_strong}http://$ip4:8000${reset}" + fi + if [ -n "$hostName" ]; then + echo -e " Tailscale URL - Machine Name: ${cyan_fg_strong}http://$hostName:8000${reset}" + fi + if [ -n "$dnsName" ]; then + echo -e " Tailscale URL - MagicDNS Name: ${cyan_fg_strong}http://$dnsName:8000${reset}" + fi + + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" +} + +######################################################################################## +######################################################################################## +####################### HOME MENU FUNCTIONS ########################################## +######################################################################################## +######################################################################################## + +# Exit Function +exit_program() { clear - echo -e "${blue_fg_strong}/ Home / Support${reset}" - echo "------------------------------------------------" - echo "What would you like to do?" - echo "1. I want to report an issue" - echo "2. Documentation" - echo "3. Discord" - echo "0. Back to Home" + echo "Bye!" + exit 0 +} - read -p "Choose Your Destiny: " support_choice +# Function to find a suitable terminal emulator with proper fallbacks +find_terminal() { + # List of common terminal emulators in priority order + local terminals=( + "gnome-terminal" # GNOME + "konsole" # KDE + "xfce4-terminal" # XFCE + "mate-terminal" # MATE + "lxterminal" # LXDE + "kitty" # Kitty + "alacritty" # Alacritty + "tilix" # Tilix + "terminator" # Terminator + "urxvt" # RXVT + "xterm" # XTerm + "x-terminal-emulator" # Debian/Ubuntu fallback + ) -############## SUPPORT - BACKEND ########################## - case $support_choice in - 1) issue_report ;; - 2) documentation ;; - 3) discord ;; - 0) home ;; - *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" - read -p "Press Enter to continue..." - support ;; + # First check the $TERMINAL environment variable + if [ -n "$TERMINAL" ] && command -v "$TERMINAL" >/dev/null 2>&1; then + echo "$TERMINAL" + return 0 + fi + + # Check the list of known terminals + for term in "${terminals[@]}"; do + if command -v "$term" >/dev/null 2>&1; then + echo "$term" + return 0 + fi + done + + # Final fallback to x-terminal-emulator + if command -v "x-terminal-emulator" >/dev/null 2>&1; then + echo "x-terminal-emulator" + return 0 + fi + + # If no terminal found, return error + return 1 +} + +start_st() { + check_nodejs + + local start_script_path="$st_install_path/start.sh" + local detected_terminal + + if [ "$LAUNCH_NEW_WIN" = "0" ]; then + log_message "INFO" "SillyTavern launched" + (cd "$st_install_path" && exec "./start.sh") + else + log_message "INFO" "SillyTavern launched in a new window." + detected_terminal=$(find_terminal) + + if [ $? -ne 0 ]; then + log_message "ERROR" "No terminal emulator found! Falling back to current shell" + (cd "$st_install_path" && exec "./start.sh") + return + fi + + log_message "INFO" "Found terminal: $detected_terminal" + + # macOS handling + if [ "$(uname)" = "Darwin" ]; then + log_message "INFO" "Detected macOS. Opening new Terminal window." + osascript < / Home / SillyTavern Remote Link |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + + # Warning and confirmation prompt + echo + echo -e "${blue_bg}${bold}╔═══════════════ CLOUDFLARE TUNNEL ═══════════════════════════════════════════════════╗${reset}" + echo -e "${blue_bg}${bold}║ WARNING: This script downloads and runs the latest cloudflared from Cloudflare to ║${reset}" + echo -e "${blue_bg}${bold}║ set up an HTTPS tunnel to your SillyTavern. ║${reset}" + echo -e "${blue_bg}${bold}║ ║${reset}" + echo -e "${blue_bg}${bold}║ Using the randomly generated temporary tunnel URL, anyone can access your ║${reset}" + echo -e "${blue_bg}${bold}║ SillyTavern over the Internet while the tunnel is active. ║${reset}" + echo -e "${blue_bg}${bold}║ ║${reset}" + echo -e "${blue_bg}${bold}║ Keep the URL safe and secure your SillyTavern installation by setting a username ║${reset}" + echo -e "${blue_bg}${bold}║ and password in config.yaml. ║${reset}" + echo -e "${blue_bg}${bold}║ ║${reset}" + echo -e "${blue_bg}${bold}║ See https://docs.sillytavern.app/usage/remoteconnections/ for more details about ║${reset}" + echo -e "${blue_bg}${bold}║ how to secure your SillyTavern install. ║${reset}" + echo -e "${blue_bg}${bold}║ ║${reset}" + echo -e "${blue_bg}${bold}║ By continuing you confirm that you're aware of the potential dangers of having a ║${reset}" + echo -e "${blue_bg}${bold}║ tunnel open and take all responsibility to properly use and secure it. ║${reset}" + echo -e "${blue_bg}${bold}╚═════════════════════════════════════════════════════════════════════════════════════╝${reset}" + echo + echo -n -e "${yellow_fg_strong}Are you sure you want to continue? [Y/N]: ${reset}" + read -r confirm + + case "$confirm" in + [Yy]*) + # Check if cloudflared is already downloaded, if not, download it + if [ ! -f cloudflared ]; then + echo "Downloading cloudflared..." + curl -Lo cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 + chmod +x cloudflared + fi + + # Run cloudflared tunnel + ./cloudflared tunnel --url localhost:8000 + start_st + ;; + [Nn]*) + home + ;; + *) + log_message "ERROR" "Invalid input. Please enter Y or N." + read -p "Press Enter to try again..." + start_st_remotelink + ;; esac } -# Check if the script is running on macOS -if [ "$(uname)" == "Darwin" ]; then - IS_MACOS="1" -fi +launch_custom_shortcut() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." + home -# Detect the package manager and execute the appropriate installation -if [ -n "$IS_MACOS" ]; then - log_message "INFO" "${blue_fg_strong}Detected macOS system.${reset}" - # macOS - install_git - install_nodejs +} + +update_manager() { + log_message "INFO" "coming soon" + read -p "Press Enter to continue..." home -# Detect the package manager and execute the appropriate installation -elif command -v apt-get &>/dev/null; then - log_message "INFO" "Detected Debian/Ubuntu-based system.${reset}" - # Debian/Ubuntu - install_git - install_nodejs + +} + +info_vram() { + # Clear the screen + clear + + # Get GPU information using lspci and filter for VGA compatible controllers + gpu_info=$(lspci | grep -i vga) + if [ -z "$gpu_info" ]; then + gpu_info="GPU information not found" + fi + + # Get VRAM size using nvidia-smi (for NVIDIA GPUs) or fallback to other methods + if command -v nvidia-smi &> /dev/null; then + UVRAM=$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits | awk '{print $1/1024}') + else + UVRAM=0 + echo "DEBUG: VRAM could not be detected. Defaulting to 0." + fi + + # Handle undefined or invalid UVRAM + if [ -z "$UVRAM" ] || [ "$UVRAM" = "Property not found" ]; then + UVRAM=0 + echo "DEBUG: VRAM could not be detected. Defaulting to 0." + fi + + # Display header + echo -e "${blue_fg_strong}| > / Home / VRAM & LLM Info |${reset}" + echo -e "${blue_fg_strong}======================================================================================================${reset}" + + # Display GPU information + echo -e "${cyan_fg_strong}GPU: $gpu_info${reset}" + echo -e "${cyan_fg_strong}GPU VRAM: $UVRAM GB${reset}" + + # Recommendations based on VRAM size + if (( $(echo "$UVRAM < 8" | bc -l) )); then + echo "It's recommended to stick with APIs like OpenAI, Claude, or OpenRouter for LLM usage." + echo "Local models will result in memory errors or perform very slowly." + elif (( $(echo "$UVRAM < 12" | bc -l) )); then + echo "Great for 7B and 8B models. Check info below for BPW (Bits Per Weight)." + display_bpw_table + elif (( $(echo "$UVRAM < 22" | bc -l) )); then + echo "Great for 7B, 8B, and 13B models. Check info below for BPW (Bits Per Weight)." + display_bpw_table + elif (( $(echo "$UVRAM < 25" | bc -l) )); then + echo "Great for 7B, 8B, 13B, and 30B models. Check info below for BPW (Bits Per Weight)." + display_bpw_table + elif (( $(echo "$UVRAM >= 25" | bc -l) )); then + echo "Great for 7B, 8B, 13B, 30B, and 70B models. Check info below for BPW (Bits Per Weight)." + display_bpw_table + else + echo "An unexpected amount of VRAM detected or unable to detect VRAM. Check your system specifications." + fi + + # Ask if the user wants to check the VRAM calculator website + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| |${reset}" + read -p " Check for compatible models on VRAM calculator website? [Y/N]: " info_vram_choice + info_vram_choice=$(echo "$info_vram_choice" | tr '[:upper:]' '[:lower:]') + + if [ "$info_vram_choice" = "y" ]; then + xdg-open "https://sillytavernai.com/llm-model-vram-calculator/?vram=$UVRAM" + fi + + # Return to the home menu home -elif command -v yum &>/dev/null; then - log_message "INFO" "Detected Red Hat/Fedora-based system.${reset}" - # Red Hat/Fedora +} + +# Function to display the BPW (Bits Per Weight) table +display_bpw_table() { + echo + echo "╔══ EXL2 - RECOMMENDED BPW [Bits Per Weight] ═════════════════════════════════════════════════════════════════════════════════╗" + echo "║ Branch ║ Bits ║ lm_head bits ║ VRAM - 4k ║ VRAM - 8k ║ VRAM - 16k ║ VRAM - 32k ║ Description ║" + echo "║═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════║" + echo "║ 8.0 ║ 8.0 ║ 8.0 ║ 10.1 GB ║ 10.5 GB ║ 11.5 GB ║ 13.6 GB ║ Maximum quality that ExLlamaV2 ║" + echo "║ ║ ║ ║ ║ ║ ║ ║ can produce, near unquantized performance. ║" + echo "║═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════║" + echo "║ 6.5 ║ 6.5 ║ 8.0 ║ 8.9 GB ║ 9.3 GB ║ 10.3 GB ║ 12.4 GB ║ Similar to 8.0, good tradeoff of ║" + echo "║ ║ ║ ║ ║ ║ ║ ║ size vs performance, RECOMMENDED. ║" + echo "║═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════║" + echo "║ 5.0 ║ 5.0 ║ 6.0 ║ 7.7 GB ║ 8.1 GB ║ 9.1 GB ║ 11.2 GB ║ Slightly lower quality vs 6.5, ║" + echo "║ ║ ║ ║ ║ ║ ║ ║ but usable on 8GB cards. ║" + echo "║═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════║" + echo "║ 4.25 ║ 4.25 ║ 6.0 ║ 7.0 GB ║ 7.4 GB ║ 8.4 GB ║ 10.5 GB ║ GPTQ equivalent bits per weight, ║" + echo "║ ║ ║ ║ ║ ║ ║ ║ slightly higher quality. ║" + echo "║═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════║" + echo "║ 3.5 ║ 3.5 ║ 6.0 ║ 6.4 GB ║ 6.8 GB ║ 7.8 GB ║ 9.9 GB ║ Lower quality, only use if you have to. ║" + echo "╚═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝" + echo +} + +############################################################ +################## HOME - FRONTEND ######################### +############################################################ +home() { + echo -e "\033]0;STL [HOME]\007" + clear + echo -e "${blue_fg_strong}| > / Home |${reset}" + echo -e "${blue_fg_strong}==============================================================${reset}" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| What would you like to do? |${reset}" + echo " 1. Update & Start SillyTavern" + echo " 2. Start SillyTavern" + echo " 3. Start SillyTavern With Remote Link" + echo " 4. Create Custom App Shortcut" + echo " 5. Update Manager" + echo " 6. Toolbox" + echo " 7. Troubleshooting & Support" + echo " 8. More info about LLM models your GPU can run." + # DEBUG CURRENT PATH + #echo -e "$(pwd)" + #echo -e "$stl_root" + #echo "$(dirname "$(realpath "$0")")" + echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" + echo -e "${cyan_fg_strong}| Menu Options: |${reset}" + echo " 0. Exit" + + # Display version and compatibility status + display_version_status + + read -p " Choose Your Destiny: " home_choice + + # Default to choice 1 if no input is provided + if [ -z "$home_choice" ]; then + home_choice=1 + fi + + +################## HOME - BACKEND ######################### + case $home_choice in + 1) update_start_st ;; + 2) start_st ;; + 3) start_st_remotelink ;; + 4) launch_custom_shortcut ;; + 5) update_manager ;; + 6) toolbox ;; + 7) troubleshooting ;; + 8) info_vram ;; + 0) exit_program ;; + *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" + read -p "Press Enter to continue..." + home ;; + esac +} + +# Startup functions +startup() { + create_logs_folder + check_path_spaces + check_path_special_chars install_git + check_launcher_updates + create_directories + create_module_files install_nodejs - home -elif command -v apk &>/dev/null; then - log_message "INFO" "Detected Alpine Linux-based system.${reset}" - # Alpine Linux - install_git - install_nodejs - home -elif command -v pacman &>/dev/null; then - log_message "INFO" "Detected Arch Linux-based system.${reset}" - # Arch Linux - install_git - install_nodejs - home -elif command -v emerge &>/dev/null; then - log_message "INFO" "Detected Gentoo Linux-based system. Now you are the real CHAD${reset}" - # Gentoo Linux - install_git - install_nodejs - home -else - log_message "ERROR" "${red_fg_strong}Unsupported package manager. Cannot detect Linux distribution.${reset}" - exit 1 -fi + check_miniconda + check_sillytavern_folder + check_sillytavern_updates + + # Functions related for displaying status + cd "$stl_root" + + get_current_branch + manage_gpu_counter + detect_gpu_info + read_tailscale_status + get_sillytavern_version + node_version=$(node -v) + stl_version="24.1.0.0" + update_status_st="Up to date" +} + +# Run startup functions +startup + +# Display the main menu +home \ No newline at end of file