2024-03-01 10:09:30 -08:00
#!/bin/bash
2024-03-04 15:24:18 -08:00
# Call function to send telemetry event
log_event( ) {
if [ -n $1 ] ; then
2024-03-16 23:13:18 -07:00
poetry run python skyvern/analytics.py $1
2024-03-04 15:24:18 -08:00
fi
}
2024-03-01 10:09:30 -08:00
# Function to check if a command exists
command_exists( ) {
command -v " $1 " & > /dev/null
}
2024-03-22 17:40:03 -04:00
ensure_required_commands( ) {
# Ensure required commands are available
2024-07-02 19:20:47 +03:00
for cmd in poetry npm; do
2024-03-22 17:40:03 -04:00
if ! command_exists " $cmd " ; then
echo " Error: $cmd is not installed. " >& 2
exit 1
fi
done
}
2024-03-01 10:09:30 -08:00
2024-03-16 23:13:18 -07:00
# Function to update or add environment variable in .env file
update_or_add_env_var( ) {
local key = $1
local value = $2
if grep -q " ^ $key = " .env; then
# Update existing variable
sed -i.bak " s/^ $key =.*/ $key = $value / " .env && rm -f .env.bak
else
# Add new variable
echo " $key = $value " >> .env
fi
}
# Function to set up LLM provider environment variables
setup_llm_providers( ) {
echo "Configuring Large Language Model (LLM) Providers..."
echo "Note: All information provided here will be stored only on your local machine."
local model_options = ( )
# OpenAI Configuration
echo "To enable OpenAI, you must have an OpenAI API key."
read -p "Do you want to enable OpenAI (y/n)? " enable_openai
if [ [ " $enable_openai " = = "y" ] ] ; then
read -p "Enter your OpenAI API key: " openai_api_key
if [ -z " $openai_api_key " ] ; then
echo "Error: OpenAI API key is required."
echo "OpenAI will not be enabled."
else
update_or_add_env_var "OPENAI_API_KEY" " $openai_api_key "
update_or_add_env_var "ENABLE_OPENAI" "true"
2025-04-16 02:12:33 -04:00
model_options += (
"OPENAI_GPT4_1"
"OPENAI_GPT4_1_MINI"
"OPENAI_GPT4_1_NANO"
"OPENAI_GPT4O"
2025-04-16 21:34:00 -04:00
"OPENAI_O4_MINI"
"OPENAI_O3"
2025-04-16 02:12:33 -04:00
)
2024-03-16 23:13:18 -07:00
fi
else
update_or_add_env_var "ENABLE_OPENAI" "false"
fi
# Anthropic Configuration
echo "To enable Anthropic, you must have an Anthropic API key."
read -p "Do you want to enable Anthropic (y/n)? " enable_anthropic
if [ [ " $enable_anthropic " = = "y" ] ] ; then
read -p "Enter your Anthropic API key: " anthropic_api_key
if [ -z " $anthropic_api_key " ] ; then
echo "Error: Anthropic API key is required."
echo "Anthropic will not be enabled."
else
update_or_add_env_var "ANTHROPIC_API_KEY" " $anthropic_api_key "
update_or_add_env_var "ENABLE_ANTHROPIC" "true"
2025-04-16 02:12:33 -04:00
model_options += (
"ANTHROPIC_CLAUDE3.5_SONNET"
"ANTHROPIC_CLAUDE3.7_SONNET"
)
2024-03-16 23:13:18 -07:00
fi
else
update_or_add_env_var "ENABLE_ANTHROPIC" "false"
fi
# Azure Configuration
echo "To enable Azure, you must have an Azure deployment name, API key, base URL, and API version."
read -p "Do you want to enable Azure (y/n)? " enable_azure
if [ [ " $enable_azure " = = "y" ] ] ; then
read -p "Enter your Azure deployment name: " azure_deployment
read -p "Enter your Azure API key: " azure_api_key
read -p "Enter your Azure API base URL: " azure_api_base
read -p "Enter your Azure API version: " azure_api_version
if [ -z " $azure_deployment " ] || [ -z " $azure_api_key " ] || [ -z " $azure_api_base " ] || [ -z " $azure_api_version " ] ; then
echo "Error: All Azure fields must be populated."
echo "Azure will not be enabled."
else
update_or_add_env_var "AZURE_DEPLOYMENT" " $azure_deployment "
update_or_add_env_var "AZURE_API_KEY" " $azure_api_key "
update_or_add_env_var "AZURE_API_BASE" " $azure_api_base "
update_or_add_env_var "AZURE_API_VERSION" " $azure_api_version "
update_or_add_env_var "ENABLE_AZURE" "true"
2025-04-16 02:12:33 -04:00
model_options += (
"AZURE_OPENAI_GPT4O"
)
2024-03-16 23:13:18 -07:00
fi
else
update_or_add_env_var "ENABLE_AZURE" "false"
fi
2024-12-02 15:51:18 -08:00
#Gemini Configuartion
echo "To enable Gemini, you must have an Gemini API key."
read -p "Do you want to enable Gemini (y/n)? " enable_gemini
if [ [ " $enable_gemini " = = "y" ] ] ; then
read -p "Enter your Gemini API key: " gemini_api_key
if [ -z " $gemini_api_key " ] ; then
echo "Error: Gemini API key is required."
echo "Gemini will not be enabled."
else
update_or_add_env_var "GEMINI_API_KEY" " $gemini_api_key "
update_or_add_env_var "ENABLE_GEMINI" "true"
2025-04-06 00:03:24 -04:00
model_options += (
"GEMINI_FLASH_2_0"
"GEMINI_FLASH_2_0_LITE"
"GEMINI_2.5_PRO_PREVIEW_03_25"
"GEMINI_2.5_PRO_EXP_03_25"
)
2024-12-02 15:51:18 -08:00
fi
else
update_or_add_env_var "ENABLE_GEMINI" "false"
fi
2025-01-11 13:08:37 +08:00
# Novita AI Configuration
echo "To enable Novita AI, you must have an Novita AI API key."
read -p "Do you want to enable Novita AI (y/n)? " enable_novita
if [ [ " $enable_novita " = = "y" ] ] ; then
read -p "Enter your Novita AI API key: " novita_api_key
if [ -z " $novita_api_key " ] ; then
echo "Error: Novita AI API key is required."
echo "Novita AI will not be enabled."
else
update_or_add_env_var "NOVITA_API_KEY" " $novita_api_key "
update_or_add_env_var "ENABLE_NOVITA" "true"
model_options += (
2025-01-28 07:51:09 +08:00
"NOVITA_DEEPSEEK_R1"
"NOVITA_DEEPSEEK_V3"
2025-01-11 13:08:37 +08:00
"NOVITA_LLAMA_3_3_70B"
"NOVITA_LLAMA_3_2_1B"
"NOVITA_LLAMA_3_2_3B"
"NOVITA_LLAMA_3_2_11B_VISION"
"NOVITA_LLAMA_3_1_8B"
"NOVITA_LLAMA_3_1_70B"
"NOVITA_LLAMA_3_1_405B"
"NOVITA_LLAMA_3_8B"
"NOVITA_LLAMA_3_70B"
)
fi
else
update_or_add_env_var "ENABLE_NOVITA" "false"
fi
2025-04-20 20:25:59 -04:00
# OpenAI Compatible Configuration
echo "To enable an OpenAI-compatible provider, you must have a model name, API key, and API base URL."
read -p "Do you want to enable an OpenAI-compatible provider (y/n)? " enable_openai_compatible
if [ [ " $enable_openai_compatible " = = "y" ] ] ; then
read -p "Enter the model name (e.g., 'yi-34b', 'mistral-large'): " openai_compatible_model_name
read -p "Enter your API key: " openai_compatible_api_key
read -p "Enter the API base URL (e.g., 'https://api.together.xyz/v1'): " openai_compatible_api_base
read -p "Does this model support vision (y/n)? " openai_compatible_vision
if [ -z " $openai_compatible_model_name " ] || [ -z " $openai_compatible_api_key " ] || [ -z " $openai_compatible_api_base " ] ; then
echo "Error: All required fields must be populated."
echo "OpenAI-compatible provider will not be enabled."
else
update_or_add_env_var "OPENAI_COMPATIBLE_MODEL_NAME" " $openai_compatible_model_name "
update_or_add_env_var "OPENAI_COMPATIBLE_API_KEY" " $openai_compatible_api_key "
update_or_add_env_var "OPENAI_COMPATIBLE_API_BASE" " $openai_compatible_api_base "
# Set vision support
if [ [ " $openai_compatible_vision " = = "y" ] ] ; then
update_or_add_env_var "OPENAI_COMPATIBLE_SUPPORTS_VISION" "true"
else
update_or_add_env_var "OPENAI_COMPATIBLE_SUPPORTS_VISION" "false"
fi
update_or_add_env_var "ENABLE_OPENAI_COMPATIBLE" "true"
model_options += (
"OPENAI_COMPATIBLE"
)
fi
else
update_or_add_env_var "ENABLE_OPENAI_COMPATIBLE" "false"
fi
2024-03-16 23:13:18 -07:00
# Model Selection
if [ ${# model_options [@] } -eq 0 ] ; then
echo "No LLM providers enabled. You won't be able to run Skyvern unless you enable at least one provider. You can re-run this script to enable providers or manually update the .env file."
else
echo "Available LLM models based on your selections:"
for i in " ${ !model_options[@] } " ; do
echo " $(( i+1)) . ${ model_options [ $i ] } "
done
read -p " Choose a model by number (e.g., 1 for ${ model_options [0] } ): " model_choice
chosen_model = ${ model_options [ $(( model_choice-1)) ] }
echo " Chosen LLM Model: $chosen_model "
2024-03-17 20:27:44 -07:00
update_or_add_env_var "LLM_KEY" " $chosen_model "
2024-03-16 23:13:18 -07:00
fi
echo "LLM provider configurations updated in .env."
}
2024-03-06 15:44:58 -08:00
# Function to initialize .env file
initialize_env_file( ) {
if [ -f ".env" ] ; then
echo ".env file already exists, skipping initialization."
2024-03-16 23:13:18 -07:00
read -p "Do you want to go through LLM provider setup again (y/n)? " redo_llm_setup
if [ [ " $redo_llm_setup " = = "y" ] ] ; then
setup_llm_providers
fi
2024-03-06 15:44:58 -08:00
return
fi
echo "Initializing .env file..."
cp .env.example .env
2024-03-16 23:13:18 -07:00
setup_llm_providers
2024-03-06 15:44:58 -08:00
# Ask for email or generate UUID
2024-03-06 19:06:15 -08:00
read -p "Please enter your email for analytics (press enter to skip): " analytics_id
2024-03-06 15:44:58 -08:00
if [ -z " $analytics_id " ] ; then
analytics_id = $( uuidgen)
fi
2024-03-16 23:13:18 -07:00
update_or_add_env_var "ANALYTICS_ID" " $analytics_id "
2024-03-06 15:44:58 -08:00
echo ".env file has been initialized."
}
2024-07-02 19:20:47 +03:00
initialize_frontend_env_file( ) {
if [ -f "skyvern-frontend/.env" ] ; then
echo "skyvern-frontend/.env file already exists, skipping initialization."
return
fi
echo "Initializing skyvern-frontend/.env file..."
cp skyvern-frontend/.env.example skyvern-frontend/.env
echo "skyvern-frontend/.env file has been initialized."
}
2024-03-01 10:09:30 -08:00
# Function to remove Poetry environment
remove_poetry_env( ) {
local env_path
env_path = $( poetry env info --path)
if [ -d " $env_path " ] ; then
rm -rf " $env_path "
echo " Removed the poetry environment at $env_path . "
else
echo "No poetry environment found."
fi
}
2024-03-14 12:55:02 -07:00
# Choose python version
choose_python_version_or_fail( ) {
2024-03-22 17:40:03 -04:00
# https://github.com/python-poetry/poetry/issues/2117
# Py --list-paths
# This will output which paths are being used for Python 3.11
# Windows users need to poetry env use {{ Py --list-paths with 3.11}}
poetry env use python3.11 || { echo "Error: Python 3.11 is not installed. If you're on Windows, check out https://github.com/python-poetry/poetry/issues/2117 to unblock yourself" ; exit 1; }
2024-03-14 12:55:02 -07:00
}
2024-03-01 10:09:30 -08:00
# Function to install dependencies
install_dependencies( ) {
poetry install
2024-07-02 19:20:47 +03:00
echo "Installing frontend dependencies"
cd skyvern-frontend
npm install --silent
cd ..
echo "Frontend dependencies installed."
2024-03-01 10:09:30 -08:00
}
activate_poetry_env( ) {
source " $( poetry env info --path) /bin/activate "
}
2024-03-03 18:14:17 -08:00
install_dependencies_after_poetry_env( ) {
2024-03-04 15:24:18 -08:00
echo "Installing playwright dependencies..."
2024-03-03 18:14:17 -08:00
playwright install
}
2024-03-01 10:09:30 -08:00
# Function to setup PostgreSQL
setup_postgresql( ) {
echo "Installing postgresql using brew"
2024-03-15 23:27:03 -04:00
# Attempt to connect to the default PostgreSQL service if it's already running via psql
if command_exists psql; then
if pg_isready; then
echo "PostgreSQL is already running locally."
# Assuming the local PostgreSQL setup is ready for use
if psql skyvern -U skyvern -c '\q' ; then
echo "Connection successful. Database and user exist."
else
createuser skyvern
createdb skyvern -O skyvern
echo "Database and user created successfully."
fi
return 0
2024-03-03 18:14:17 -08:00
fi
fi
2024-03-15 23:27:03 -04:00
# Check if Docker is installed and running
if ! command_exists docker || ! docker info > /dev/null 2>& 1; then
echo "Docker is not running or not installed. Please install or start Docker and try again."
exit 1
fi
# Check if PostgreSQL is already running in a Docker container
if docker ps | grep -q postgresql-container; then
echo "PostgreSQL is already running in a Docker container."
else
# Attempt to install and start PostgreSQL using Docker
echo "Attempting to install PostgreSQL via Docker..."
docker run --name postgresql-container -e POSTGRES_HOST_AUTH_METHOD = trust -d -p 5432:5432 postgres:14
echo "PostgreSQL has been installed and started using Docker."
# Wait for PostgreSQL to start
echo "Waiting for PostgreSQL to start..."
sleep 20 # Adjust sleep time as necessary
fi
# Assuming docker exec works directly since we've checked Docker's status before
if docker exec postgresql-container psql -U postgres -c "\du" | grep -q skyvern; then
echo "Database user exists."
else
echo "Creating database user..."
docker exec postgresql-container createuser -U postgres skyvern
fi
2024-03-01 10:09:30 -08:00
2024-03-15 23:27:03 -04:00
if docker exec postgresql-container psql -U postgres -lqt | cut -d \| -f 1 | grep -qw skyvern; then
echo "Database exists."
2024-03-01 10:09:30 -08:00
else
2024-03-15 23:27:03 -04:00
echo "Creating database..."
docker exec postgresql-container createdb -U postgres skyvern -O skyvern
2024-03-01 10:09:30 -08:00
echo "Database and user created successfully."
fi
}
# Function to run Alembic upgrade
run_alembic_upgrade( ) {
echo "Running Alembic upgrade..."
alembic upgrade head
}
# Function to create organization and API token
create_organization( ) {
echo "Creating organization and API token..."
local org_output api_token
2024-03-16 23:13:18 -07:00
org_output = $( poetry run python scripts/create_organization.py Skyvern-Open-Source)
2024-03-01 10:09:30 -08:00
api_token = $( echo " $org_output " | awk '/token=/{gsub(/.*token=' \' '|' \' '.*/, ""); print}' )
# Ensure .streamlit directory exists
mkdir -p .streamlit
# Check if secrets.toml exists and back it up
if [ -f ".streamlit/secrets.toml" ] ; then
mv .streamlit/secrets.toml .streamlit/secrets.backup.toml
echo "Existing secrets.toml file backed up as secrets.backup.toml"
fi
# Update the secrets-open-source.toml file
2024-03-22 12:01:12 +08:00
echo -e " [skyvern]\nconfigs = [\n {\"env\" = \"local\", \"host\" = \"http://127.0.0.1:8000/api/v1\", \"orgs\" = [{name=\"Skyvern\", cred=\" $api_token \"}]}\n] " > .streamlit/secrets.toml
2024-03-01 10:09:30 -08:00
echo ".streamlit/secrets.toml file updated with organization details."
2024-07-02 19:20:47 +03:00
# Check if skyvern-frontend/.env exists and back it up
# This is redundant for first time set up but useful for subsequent runs
if [ -f "skyvern-frontend/.env" ] ; then
mv skyvern-frontend/.env skyvern-frontend/.env.backup
echo "Existing skyvern-frontend/.env file backed up as skyvern-frontend/.env.backup"
cp skyvern-frontend/.env.example skyvern-frontend/.env
fi
# Update the skyvern-frontend/.env file
# sed wants a backup file extension, and providing empty string doesn't work on all platforms
sed -i".old" -e " s/YOUR_API_KEY/ $api_token /g " skyvern-frontend/.env
echo "skyvern-frontend/.env file updated with API token."
2024-03-01 10:09:30 -08:00
}
# Main function
main( ) {
2024-03-22 17:40:03 -04:00
ensure_required_commands
2024-03-06 15:44:58 -08:00
initialize_env_file
2024-07-02 19:20:47 +03:00
initialize_frontend_env_file
2024-03-14 12:55:02 -07:00
choose_python_version_or_fail
2024-03-01 10:09:30 -08:00
remove_poetry_env
install_dependencies
setup_postgresql
activate_poetry_env
2024-03-03 18:14:17 -08:00
install_dependencies_after_poetry_env
2024-03-01 10:09:30 -08:00
run_alembic_upgrade
create_organization
2024-03-04 15:24:18 -08:00
log_event "skyvern-oss-setup-complete"
2024-03-01 10:09:30 -08:00
echo "Setup completed successfully."
}
# Execute main function
2024-03-06 19:06:15 -08:00
main