-
Notifications
You must be signed in to change notification settings - Fork 751
/
setup.sh
executable file
·327 lines (288 loc) · 11.8 KB
/
setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#!/bin/bash
# Call function to send telemetry event
log_event() {
if [ -n $1 ]; then
poetry run python skyvern/analytics.py $1
fi
}
# Function to check if a command exists
command_exists() {
command -v "$1" &> /dev/null
}
ensure_required_commands() {
# Ensure required commands are available
for cmd in poetry npm; do
if ! command_exists "$cmd"; then
echo "Error: $cmd is not installed." >&2
exit 1
fi
done
}
# 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"
model_options+=("OPENAI_GPT4_TURBO" "OPENAI_GPT4V" "OPENAI_GPT4O")
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"
model_options+=("ANTHROPIC_CLAUDE3_OPUS" "ANTHROPIC_CLAUDE3_SONNET" "ANTHROPIC_CLAUDE3_HAIKU" "ANTHROPIC_CLAUDE3.5_SONNET")
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"
model_options+=("AZURE_OPENAI_GPT4V")
fi
else
update_or_add_env_var "ENABLE_AZURE" "false"
fi
#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"
model_options+=("GEMINI_PRO")
fi
else
update_or_add_env_var "ENABLE_GEMINI" "false"
fi
# 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"
update_or_add_env_var "LLM_KEY" "$chosen_model"
fi
echo "LLM provider configurations updated in .env."
}
# Function to initialize .env file
initialize_env_file() {
if [ -f ".env" ]; then
echo ".env file already exists, skipping initialization."
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
return
fi
echo "Initializing .env file..."
cp .env.example .env
setup_llm_providers
# Ask for email or generate UUID
read -p "Please enter your email for analytics (press enter to skip): " analytics_id
if [ -z "$analytics_id" ]; then
analytics_id=$(uuidgen)
fi
update_or_add_env_var "ANALYTICS_ID" "$analytics_id"
echo ".env file has been initialized."
}
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."
}
# 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
}
# Choose python version
choose_python_version_or_fail() {
# 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; }
}
# Function to install dependencies
install_dependencies() {
poetry install
echo "Installing frontend dependencies"
cd skyvern-frontend
npm install --silent
cd ..
echo "Frontend dependencies installed."
}
activate_poetry_env() {
source "$(poetry env info --path)/bin/activate"
}
install_dependencies_after_poetry_env() {
echo "Installing playwright dependencies..."
playwright install
}
# Function to setup PostgreSQL
setup_postgresql() {
echo "Installing postgresql using brew"
# 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
fi
fi
# 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
if docker exec postgresql-container psql -U postgres -lqt | cut -d \| -f 1 | grep -qw skyvern; then
echo "Database exists."
else
echo "Creating database..."
docker exec postgresql-container createdb -U postgres skyvern -O skyvern
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
org_output=$(poetry run python scripts/create_organization.py Skyvern-Open-Source)
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
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
echo ".streamlit/secrets.toml file updated with organization details."
# 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."
}
# Main function
main() {
ensure_required_commands
initialize_env_file
initialize_frontend_env_file
choose_python_version_or_fail
remove_poetry_env
install_dependencies
setup_postgresql
activate_poetry_env
install_dependencies_after_poetry_env
run_alembic_upgrade
create_organization
log_event "skyvern-oss-setup-complete"
echo "Setup completed successfully."
}
# Execute main function
main