#!/bin/bash # # SillyTavern Launcher # Created by: Deffcolony # # Description: # This script runs SillyTavern and/or Extras on your Linux system. # # Usage: # chmod +x launcher.sh && ./launcher.sh # # In automated environments, you may want to run as root. # If using curl, we recommend using the -fsSL flags. # # This script is intended for use on Linux systems. Please # report any issues or bugs on the GitHub repository. # # App Github: https://github.com/SillyTavern/SillyTavern.git # # GitHub: https://github.com/SillyTavern/SillyTavern-Launcher # Issues: https://github.com/SillyTavern/SillyTavern-Launcher/issues # ---------------------------------------------------------- # Note: Modify the script as needed to fit your requirements. # ---------------------------------------------------------- echo -e "\033]0;STL\007" # ANSI Escape Code for Colors reset="\033[0m" white_fg_strong="\033[90m" red_fg_strong="\033[91m" green_fg_strong="\033[92m" yellow_fg_strong="\033[93m" blue_fg_strong="\033[94m" magenta_fg_strong="\033[95m" cyan_fg_strong="\033[96m" # Normal Background Colors red_bg="\033[41m" blue_bg="\033[44m" yellow_bg="\033[43m" # 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_linux" # 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 log_message() { # This is only time current_time=$(date +'%H:%M:%S') # This is with date and time # current_time=$(date +'%Y-%m-%d %H:%M:%S') case "$1" in "INFO") echo -e "${blue_bg}[$current_time]${reset} ${blue_fg_strong}[INFO]${reset} $2" ;; "WARN") echo -e "${yellow_bg}[$current_time]${reset} ${yellow_fg_strong}[WARN]${reset} $2" ;; "ERROR") echo -e "${red_bg}[$current_time]${reset} ${red_fg_strong}[ERROR]${reset} $2" ;; *) echo -e "${blue_bg}[$current_time]${reset} ${blue_fg_strong}[DEBUG]${reset} $2" ;; esac } # Log your messages test window #log_message "INFO" "Something has been launched." #log_message "WARN" "${yellow_fg_strong}Something is not installed on this system.${reset}" #log_message "ERROR" "${red_fg_strong}An error occurred during the process.${reset}" #log_message "DEBUG" "This is a debug message." #read -p "Press Enter to continue..." # Function to find Miniconda installation directory find_conda() { local paths=( "$HOME/miniconda3" "$HOME/miniconda" "/opt/miniconda3" "/opt/miniconda" "/usr/local/miniconda3" "/usr/local/miniconda" "/usr/miniconda3" "/usr/miniconda" "$HOME/anaconda3" "$HOME/anaconda" "/opt/anaconda3" "/opt/anaconda" "/usr/local/anaconda3" "/usr/local/anaconda" "/usr/anaconda3" "/usr/anaconda" ) for path in "${paths[@]}"; do if [ -d "$path" ]; then echo "$path" return 0 fi done return 1 } # 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}" 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 log_message "INFO" "${blue_fg_strong}Git is already installed.${reset}" fi } # Function to check if Node.js is installed check_nodejs() { node --version > /dev/null 2>&1 if [ $? -ne 0 ]; then echo -e "${red_fg_strong}[ERROR] node command not found in PATH${reset}" echo -e "${red_bg}Please make sure Node.js is installed and added to your PATH.${reset}" echo -e "${blue_bg}To install Node.js, go to Toolbox${reset}" read -p "Press Enter to continue..." home fi } # Function to start SillyTavern with Extras start_extras() { check_nodejs if [ "$LAUNCH_NEW_WIN" = "0" ]; then local main_pid=$! log_message "INFO" "Extras launched under pid $main_pid" { #has to be after the first one, so we are 1 directory up cd "SillyTavern-extras" || { log_message "ERROR" "SillyTavern-extras directory not found. Please make sure you have installed SillyTavern-extras." kill $main_pid exit 1 } log_message "INFO" "Working dir: $(pwd)" ./start.sh } & local extras_pid=$! log_message "INFO" "Extras launched under pid $extras_pid" wait $main_pid kill $extras_pid else cd "SillyTavern-extras" log_message "INFO" "Extras 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 --args --title="SillyTavern Extras" --working-directory="SillyTavern-extras" --command "python server.py --listen --rvc-save-file --max-content-length=1000 --enable-modules=rvc,caption; exec bash" else exec "$detected_terminal" -e "python server.py --listen --rvc-save-file --max-content-length=1000 --enable-modules=rvc,caption; bash" fi fi home } # Function to start xtts start_xtts() { check_nodejs if [ "$LAUNCH_NEW_WIN" = "0" ]; then local main_pid=$! log_message "INFO" "xtts launched under pid $main_pid" # Move to xtts directory cd "xtts" || { log_message "ERROR" "xtts directory not found. Please make sure you have installed xtts" kill "$main_pid" exit 1 } log_message "INFO" "Working dir: $(pwd)" ./start.sh & local xtts_pid=$! log_message "INFO" "xtts launched under pid $xtts_pid" wait "$main_pid" kill "$xtts_pid" else cd "xtts" log_message "INFO" "xtts 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 XTTS in the detected terminal if [ "$(uname)" == "Darwin" ]; then log_message "INFO" "Detected macOS. Opening new Terminal window." open -a Terminal --args --title="XTTSv2 API Server" --working-directory="xtts" --command "conda activate xtts; python -m xtts_api_server; exec bash" else exec "$detected_terminal" -e "conda activate xtts && python -m xtts_api_server; bash" fi fi home } # Function to update update() { echo -e "\033]0;STL [UPDATE]\007" log_message "INFO" "Updating SillyTavern-Launcher..." git pull --rebase --autostash # Update SillyTavern if directory exists if [ -d "SillyTavern" ]; then log_message "INFO" "Updating SillyTavern..." cd "SillyTavern" git pull --rebase --autostash cd .. log_message "INFO" "SillyTavern updated successfully." else log_message "WARN" "SillyTavern directory not found. Skipping SillyTavern update." fi # Update Extras if directory exists if [ -d "SillyTavern-extras" ]; then log_message "INFO" "Updating SillyTavern-extras..." cd "SillyTavern-extras" git pull --rebase --autostash cd .. log_message "INFO" "SillyTavern-extras updated successfully." else log_message "WARN" "SillyTavern-extras directory not found. Skipping SillyTavern-extras update." fi # Update XTTS if directory exists if [ -d "xtts" ]; then log_message "INFO" "Updating XTTS..." cd "xtts" source activate xtts pip install --upgrade xtts-api-server conda deactivate cd .. log_message "INFO" "XTTS updated successfully." else log_message "WARN" "xtts directory not found. Skipping XTTS update." fi read -p "Press Enter to continue..." home } create_backup() { 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}" # 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 "${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 } restore_backup() { 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}" echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" echo -e "${cyan_fg_strong}| Available Backups |${reset}" backup_files=() backup_count=0 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 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 } ############################################################ ################# BACKUP - FRONTEND ######################## ############################################################ backup() { echo -e "\033]0;STL [BACKUP]\007" clear 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" 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) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." 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_npm_cache() { log_message "INFO" "Clearing npm cache..." npm cache clean --force log_message "INFO" "npm cache cleared successfully." 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 -C "$st_install_path" switch release read -p "Press Enter to continue..." switch_branch } # Function to switch to the Staging branch in SillyTavern switch_staging_st() { log_message "INFO" "Switching to staging branch..." git -C "$st_install_path" switch staging read -p "Press Enter to continue..." switch_branch } ############################################################ ############## SWITCH BRANCE - FRONTEND #################### ############################################################ switch_branch() { echo -e "\033]0;STL [SWITCH BRANCH]\007" clear 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" echo -e "${cyan_fg_strong} ______________________________________________________________${reset}" echo -e "${cyan_fg_strong}| |${reset}" read -p " Choose Your Destiny: " branch_choice ################# SWITCH BRANCE - BACKEND ######################## case $branch_choice in 1) switch_release_st ;; 2) switch_staging_st ;; 0) toolbox ;; *) echo -e "${yellow_fg_strong}WARNING: Invalid number. Please insert a valid number.${reset}" read -p "Press Enter to continue..." 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}" 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 log_message "INFO" "${blue_fg_strong}p7zip (7-Zip) is already installed.${reset}" fi } # Function to install FFmpeg install_ffmpeg() { if ! command -v ffmpeg &> /dev/null; then log_message "WARN" "${yellow_fg_strong}FFmpeg is not installed on this system${reset}" 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 log_message "INFO" "${blue_fg_strong}FFmpeg is already installed.${reset}" fi } install_nodejs() { if ! command -v node &> /dev/null; then log_message "WARN" "${yellow_fg_strong}Node.js is not installed on this system${reset}" 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 log_message "INFO" "${blue_fg_strong}Node.js is already installed.${reset}" 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 } install_tabbyapi_menu() { # Check if the tabbyapi folder exists and deactivate Conda environment if necessary if [[ -d "$tabbyapi_install_path" ]]; then log_message "INFO" "Deactivating Conda environment: tabbyapi" conda deactivate fi clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer / Text Completion / TabbyAPI |${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 TabbyAPI" echo " 2. Install ST-tabbyAPI-loader Extension" echo " 3. Models [Install Options]" 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_tabbyapi_choice echo # Handle user input case "$app_installer_tabbyapi_choice" in 1) if [[ -f "$app_installer_text_completion_dir/install_tabbyapi.sh" ]]; then bash "$app_installer_text_completion_dir/install_tabbyapi.sh" install_tabbyapi_menu else log_message "ERROR" "install_tabbyapi.sh not found in: $app_installer_text_completion_dir" read -p "Press Enter to continue..." install_tabbyapi_menu fi ;; 2) if [[ -f "$app_installer_text_completion_dir/install_tabbyapi_st_ext.sh" ]]; then bash "$app_installer_text_completion_dir/install_tabbyapi_st_ext.sh" install_tabbyapi_menu else log_message "ERROR" "install_tabbyapi_st_ext.sh not found in: $app_installer_text_completion_dir" read -p "Press Enter to continue..." install_tabbyapi_menu fi ;; 3) bash "$app_installer_text_completion_dir/install_tabbyapi_model_menu.sh" install_tabbyapi_menu ;; 0) app_installer_text_completion ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." install_tabbyapi_menu ;; esac } app_installer_text_completion() { echo -e "\033]0;STL [APP INSTALLER TEXT COMPLETION]\007" clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer / Text Completion |${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 Text generation web UI oobabooga" echo " 2. koboldcpp [Install options]" echo " 3. TabbyAPI [Install options]" echo " 4. Install llamacpp" 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_text_completion_choice case "$app_installer_text_completion_choice" in 1) if [[ -f "$app_installer_text_completion_dir/install_ooba.sh" ]]; then bash "$app_installer_text_completion_dir/install_ooba.sh" app_installer_text_completion else log_message "ERROR" "install_ooba.sh not found in: $app_installer_text_completion_dir" read -p "Press Enter to continue..." app_installer_text_completion fi ;; 2) install_koboldcpp_menu ;; 3) install_tabbyapi_menu ;; 4) if [[ -f "$app_installer_text_completion_dir/install_llamacpp.sh" ]]; then bash "$app_installer_text_completion_dir/install_llamacpp.sh" app_installer_text_completion else log_message "ERROR" "install_llamacpp.sh not found in: $app_installer_text_completion_dir" read -p "Press Enter to continue..." app_installer_text_completion fi ;; 0) app_installer ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." app_installer_text_completion ;; esac } app_installer_voice_generation() { echo -e "\033]0;STL [APP INSTALLER VOICE GENERATION]\007" clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Installer / Voice Generation |${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 AllTalk V2" echo " 2. Install AllTalk" echo " 3. Install XTTS" echo " 4. Install RVC" echo " 5. Install RVC-Python" 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_voice_generation_choice case "$app_installer_voice_generation_choice" in 1) if [[ -f "$app_installer_voice_generation_dir/install_alltalk_v2.sh" ]]; then bash "$app_installer_voice_generation_dir/install_alltalk_v2.sh" app_installer_voice_generation else log_message "ERROR" "install_alltalk_v2.sh not found in: $app_installer_voice_generation_dir" read -p "Press Enter to continue..." app_installer_voice_generation fi ;; 2) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_installer_voice_generation ;; 3) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_installer_voice_generation ;; 4) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_installer_voice_generation ;; 5) if [[ -f "$app_installer_voice_generation_dir/install_rvc_python.sh" ]]; then bash "$app_installer_voice_generation_dir/install_rvc_python.sh" app_installer_voice_generation else log_message "ERROR" "install_rvc_python.sh not found in: $app_installer_voice_generation_dir" read -p "Press Enter to continue..." app_installer_voice_generation fi ;; 0) app_installer ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." app_installer_voice_generation ;; esac } 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;STL [APP INSTALLER]\007" clear 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" 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 ################# APP INSTALLER - BACKEND ################ case $app_installer_choice in 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..." app_installer ;; esac } ######################################################################################## ######################################################################################## ####################### APP UNINSTALLER MENU FUNCTIONS ################################ ######################################################################################## ######################################################################################## # Function to uninstall Extras uninstall_extras() { echo echo -e "${red_bg}╔════ DANGER ZONE ═══════════════════════════════════════════════════════════════════╗${reset}" echo -e "${red_bg}║ WARNING: This will delete all data in Extras ║${reset}" echo -e "${red_bg}║ If you want to keep any data, make sure to create a backup before proceeding. ║${reset}" echo -e "${red_bg}╚════════════════════════════════════════════════════════════════════════════════════╝${reset}" echo echo -n "Are you sure you want to proceed? [Y/N]: " read confirmation if [ "$confirmation" = "Y" ] || [ "$confirmation" = "y" ]; then log_message "INFO" "Removing the SillyTavern-extras directory..." rm -rf SillyTavern-extras log_message "INFO" "Removing the Conda environment: extras" conda remove --name extras --all -y log_message "INFO" "${green_fg_strong}Extras uninstalled successfully.${reset}" else echo "Uninstall canceled." fi pause app_uninstaller } # Function to uninstall XTTS uninstall_xtts() { echo echo -e "${red_bg}╔════ DANGER ZONE ═══════════════════════════════════════════════════════════════════╗${reset}" echo -e "${red_bg}║ WARNING: This will delete all data in XTTS ║${reset}" echo -e "${red_bg}║ If you want to keep any data, make sure to create a backup before proceeding. ║${reset}" echo -e "${red_bg}╚════════════════════════════════════════════════════════════════════════════════════╝${reset}" echo echo -n "Are you sure you want to proceed? [Y/N]: " read confirmation if [ "$confirmation" = "Y" ] || [ "$confirmation" = "y" ]; then log_message "INFO" "Removing the xtts directory..." rm -rf xtts log_message "INFO" "Removing the Conda environment: xtts" conda remove --name xtts --all -y log_message "INFO" "${green_fg_strong}XTTS uninstalled successfully.${reset}" else echo "Uninstall canceled." fi pause app_uninstaller } # Function to uninstall SillyTavern uninstall_st() { echo echo -e "${red_bg}╔════ DANGER ZONE ═══════════════════════════════════════════════════════════════════╗${reset}" echo -e "${red_bg}║ WARNING: This will delete all data in SillyTavern ║${reset}" echo -e "${red_bg}║ If you want to keep any data, make sure to create a backup before proceeding. ║${reset}" echo -e "${red_bg}╚════════════════════════════════════════════════════════════════════════════════════╝${reset}" echo echo -n "Are you sure you want to proceed? [Y/N]: " read confirmation if [ "$confirmation" = "Y" ] || [ "$confirmation" = "y" ]; then log_message "INFO" "Removing the SillyTavern directory..." rm -rf "$st_install_path" log_message "INFO" "${green_fg_strong}SillyTavern uninstalled successfully.${reset}" else echo "Uninstall canceled." fi read -p "Press Enter to continue..." app_uninstaller_core_utilities } uninstall_p7zip() { if command -v 7z &> /dev/null; then log_message "INFO" "${blue_fg_strong}Uninstalling p7zip (7-Zip)...${reset}" 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}Failed to uninstall p7zip (7-Zip).${reset}" app_uninstaller_core_utilities fi 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 } uninstall_ffmpeg() { if command -v ffmpeg &> /dev/null; then log_message "INFO" "${blue_fg_strong}Uninstalling FFmpeg...${reset}" 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}Failed to uninstall FFmpeg.${reset}" app_uninstaller_core_utilities fi else log_message "INFO" "${blue_fg_strong}FFmpeg is not installed.${reset}" fi read -p "Press Enter to continue..." app_uninstaller_core_utilities } uninstall_nodejs() { echo -e "\033]0;STL [UNINSTALL NODEJS]\007" if command -v node &> /dev/null; then 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 node &> /dev/null; then log_message "INFO" "${green_fg_strong}Node.js successfully uninstalled.${reset}" fi else log_message "INFO" "${blue_fg_strong}Node.js is not installed.${reset}" fi read -p "Press Enter to continue..." app_uninstaller_core_utilities } uninstall_git() { if command -v git &> /dev/null; then log_message "INFO" "${blue_fg_strong}Uninstalling Git...${reset}" 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}Failed to uninstall Git.${reset}" app_uninstaller_core_utilities fi 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() { clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Uninstaller / Text Completion |${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 Text generation web UI oobabooga" echo " 2. UNINSTALL koboldcpp" echo " 3. UNINSTALL TabbyAPI" echo " 4. UNINSTALL llamacpp" 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_text_completion_choice echo # Handle user input case "$app_uninstaller_text_completion_choice" in 1) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_text_completion if [[ -f "$app_uninstaller_text_completion_dir/uninstall_ooba.sh" ]]; then bash "$app_uninstaller_text_completion_dir/uninstall_ooba.sh" app_uninstaller_text_completion else log_message "ERROR" "uninstall_ooba.sh not found in: $app_uninstaller_text_completion_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_text_completion fi ;; 2) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_text_completion if [[ -f "$app_uninstaller_text_completion_dir/uninstall_koboldcpp.sh" ]]; then bash "$app_uninstaller_text_completion_dir/uninstall_koboldcpp.sh" app_uninstaller_text_completion else log_message "ERROR" "uninstall_koboldcpp.sh not found in: $app_uninstaller_text_completion_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_text_completion fi ;; 3) if [[ -f "$app_uninstaller_text_completion_dir/uninstall_tabbyapi.sh" ]]; then bash "$app_uninstaller_text_completion_dir/uninstall_tabbyapi.sh" app_uninstaller_text_completion else log_message "ERROR" "uninstall_tabbyapi.sh not found in: $app_uninstaller_text_completion_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_text_completion fi ;; 4) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_text_completion if [[ -f "$app_uninstaller_text_completion_dir/uninstall_llamacpp.sh" ]]; then bash "$app_uninstaller_text_completion_dir/uninstall_llamacpp.sh" app_uninstaller_text_completion else log_message "ERROR" "uninstall_llamacpp.sh not found in: $app_uninstaller_text_completion_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_text_completion fi ;; 0) app_uninstaller ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." app_uninstaller_text_completion ;; esac } app_uninstaller_voice_generation() { clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Uninstaller / Voice Generation |${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 AllTalk V2" echo " 2. UNINSTALL AllTalk" echo " 3. UNINSTALL XTTS" echo " 4. UNINSTALL RVC" echo " 5. UNINSTALL RVC-Python" 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_voice_generation_choice echo # Handle user input case "$app_uninstaller_voice_generation_choice" in 1) if [[ -f "$app_uninstaller_voice_generation_dir/uninstall_alltalk_v2.sh" ]]; then bash "$app_uninstaller_voice_generation_dir/uninstall_alltalk_v2.sh" app_uninstaller_voice_generation else log_message "ERROR" "uninstall_alltalk_v2.sh not found in: $app_uninstaller_voice_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_voice_generation fi ;; 2) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_voice_generation if [[ -f "$app_uninstaller_voice_generation_dir/uninstall_alltalk.sh" ]]; then bash "$app_uninstaller_voice_generation_dir/uninstall_alltalk.sh" app_uninstaller_voice_generation else log_message "ERROR" "uninstall_alltalk.sh not found in: $app_uninstaller_voice_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_voice_generation fi ;; 3) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_voice_generation if [[ -f "$app_uninstaller_voice_generation_dir/uninstall_xtts.sh" ]]; then bash "$app_uninstaller_voice_generation_dir/uninstall_xtts.sh" app_uninstaller_voice_generation else log_message "ERROR" "uninstall_xtts.sh not found in: $app_uninstaller_voice_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_voice_generation fi ;; 4) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_voice_generation if [[ -f "$app_uninstaller_voice_generation_dir/uninstall_rvc.sh" ]]; then bash "$app_uninstaller_voice_generation_dir/uninstall_rvc.sh" app_uninstaller_voice_generation else log_message "ERROR" "uninstall_rvc.sh not found in: $app_uninstaller_voice_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_voice_generation fi ;; 5) if [[ -f "$app_uninstaller_voice_generation_dir/uninstall_rvc_python.sh" ]]; then bash "$app_uninstaller_voice_generation_dir/uninstall_rvc_python.sh" app_uninstaller_voice_generation else log_message "ERROR" "uninstall_rvc_python.sh not found in: $app_uninstaller_voice_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_voice_generation fi ;; 0) app_uninstaller ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." app_uninstaller_voice_generation ;; esac } app_uninstaller_image_generation() { clear echo -e "${blue_fg_strong}| > / Home / Toolbox / App Uninstaller / Image Generation |${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 Stable Diffusion WebUI" echo " 2. UNINSTALL Stable Diffusion WebUI Forge" echo " 3. UNINSTALL ComfyUI" echo " 4. UNINSTALL Fooocus" echo " 5. UNINSTALL InvokeAI" echo " 6. UNINSTALL Ostris AI Toolkit" 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_image_generation_choice echo # Handle user input case "$app_uninstaller_image_generation_choice" in 1) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_image_generation if [[ -f "$app_uninstaller_image_generation_dir/uninstall_sdwebui.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_sdwebui.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_sdwebui.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 2) if [[ -f "$app_uninstaller_image_generation_dir/uninstall_sdwebuiforge.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_sdwebuiforge.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_sdwebuiforge.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 3) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_image_generation if [[ -f "$app_uninstaller_image_generation_dir/uninstall_comfyui.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_comfyui.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_comfyui.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 4) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_image_generation if [[ -f "$app_uninstaller_image_generation_dir/uninstall_fooocus.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_fooocus.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_fooocus.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 5) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_image_generation if [[ -f "$app_uninstaller_image_generation_dir/uninstall_invokeai.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_invokeai.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_invokeai.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 6) log_message "INFO" "coming soon" read -p "Press Enter to continue..." app_uninstaller_image_generation if [[ -f "$app_uninstaller_image_generation_dir/uninstall_ostris_aitoolkit.sh" ]]; then bash "$app_uninstaller_image_generation_dir/uninstall_ostris_aitoolkit.sh" app_uninstaller_image_generation else log_message "ERROR" "uninstall_ostris_aitoolkit.sh not found in: $app_uninstaller_image_generation_dir" log_message "INFO" "Running Automatic Repair..." git pull read -p "Press Enter to continue..." app_uninstaller_image_generation fi ;; 0) app_uninstaller ;; *) log_message "ERROR" "Invalid input" read -p "Press Enter to continue..." app_uninstaller_image_generation ;; esac } 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;STL [APP UNINSTALLER]\007" clear 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" 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 ################# APP UNINSTALLER - BACKEND ################ case $app_uninstaller_choice in 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..." app_uninstaller ;; esac } ############################################################ ################# TOOLBOX - FRONTEND ####################### ############################################################ toolbox() { echo -e "\033]0;STL [TOOLBOX]\007" clear 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" 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_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..." toolbox ;; esac } ######################################################################################## ######################################################################################## ####################### 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" } # 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 } # 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 } # 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() { # Try to find Miniconda installation miniconda_path=$(find_conda) if [ $? -ne 0 ]; 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" return 1 fi # Source Conda initialization script if [ -f "${miniconda_path}/etc/profile.d/conda.sh" ]; then source "${miniconda_path}/etc/profile.d/conda.sh" else log_message "ERROR" "${red_fg_strong}Conda initialization script not found at ${miniconda_path}/etc/profile.d/conda.sh${reset}" log_message "INFO" "Please ensure Miniconda3 is properly installed from https://docs.conda.io/en/latest/miniconda.html" return 1 fi # Check if conda command is available if ! command -v conda &> /dev/null; then log_message "ERROR" "${red_fg_strong}Conda command not available after initialization.${reset}" log_message "INFO" "Please ensure Miniconda3 is properly installed from https://docs.conda.io/en/latest/miniconda.html" return 1 fi log_message "INFO" "${blue_fg_strong}Miniconda3 is installed at ${miniconda_path}${reset}" return 0 } # 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 "Bye!" exit 0 } # 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 ) # 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 } launch_custom_shortcut() { log_message "INFO" "coming soon" read -p "Press Enter to continue..." home } update_manager() { log_message "INFO" "coming soon" read -p "Press Enter to continue..." home } 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 } # 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 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="25.1.0.0" update_status_st="Up to date" } # Run startup functions startup # Display the main menu home