Navigare1002 commited on
Commit
82fd181
·
verified ·
1 Parent(s): 79b2285

Upload entrypoint.sh

Browse files
Files changed (1) hide show
  1. entrypoint.sh +336 -0
entrypoint.sh ADDED
@@ -0,0 +1,336 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ CONFIG_FILE="${APP_HOME}/config.yaml"
5
+
6
+ # Priority 1: Use USERNAME/PASSWORD if both are provided
7
+ if [ -n "${USERNAME}" ] && [ -n "${PASSWORD}" ]; then
8
+ echo "--- Basic auth enabled: Creating config.yaml with provided credentials. ---"
9
+
10
+ cat <<EOT > ${CONFIG_FILE}
11
+ dataRoot: ./data
12
+ listen: true
13
+ listenAddress:
14
+ ipv4: 0.0.0.0
15
+ ipv6: '[::]'
16
+ protocol:
17
+ ipv4: true
18
+ ipv6: false
19
+ dnsPreferIPv6: false
20
+ autorunHostname: "auto"
21
+ port: 8000
22
+ autorunPortOverride: -1
23
+ ssl:
24
+ enabled: false
25
+ certPath: "./certs/cert.pem"
26
+ keyPath: "./certs/privkey.pem"
27
+ whitelistMode: false
28
+ enableForwardedWhitelist: false
29
+ whitelist:
30
+ - ::1
31
+ - 127.0.0.1
32
+ whitelistDockerHosts: true
33
+ basicAuthMode: true
34
+ basicAuthUser:
35
+ username: "${USERNAME}"
36
+ password: "${PASSWORD}"
37
+ enableCorsProxy: false
38
+ requestProxy:
39
+ enabled: false
40
+ url: "socks5://username:password@example.com:1080"
41
+ bypass:
42
+ - localhost
43
+ - 127.0.0.1
44
+ enableUserAccounts: false
45
+ enableDiscreetLogin: false
46
+ autheliaAuth: false
47
+ perUserBasicAuth: false
48
+ sessionTimeout: -1
49
+ disableCsrfProtection: false
50
+ securityOverride: false
51
+ logging:
52
+ enableAccessLog: true
53
+ minLogLevel: 0
54
+ rateLimiting:
55
+ preferRealIpHeader: false
56
+ autorun: false
57
+ avoidLocalhost: false
58
+ backups:
59
+ common:
60
+ numberOfBackups: 50
61
+ chat:
62
+ enabled: true
63
+ checkIntegrity: true
64
+ maxTotalBackups: -1
65
+ throttleInterval: 10000
66
+ thumbnails:
67
+ enabled: true
68
+ format: "jpg"
69
+ quality: 95
70
+ dimensions: { 'bg': [160, 90], 'avatar': [96, 144] }
71
+ performance:
72
+ lazyLoadCharacters: false
73
+ memoryCacheCapacity: '100mb'
74
+ useDiskCache: true
75
+ allowKeysExposure: true
76
+ skipContentCheck: false
77
+ whitelistImportDomains:
78
+ - localhost
79
+ - cdn.discordapp.com
80
+ - files.catbox.moe
81
+ - raw.githubusercontent.com
82
+ requestOverrides: []
83
+ extensions:
84
+ enabled: true
85
+ autoUpdate: false
86
+ models:
87
+ autoDownload: true
88
+ classification: Cohee/distilbert-base-uncased-go-emotions-onnx
89
+ captioning: Xenova/vit-gpt2-image-captioning
90
+ embedding: Cohee/jina-embeddings-v2-base-en
91
+ speechToText: Xenova/whisper-small
92
+ textToSpeech: Xenova/speecht5_tts
93
+ enableDownloadableTokenizers: true
94
+ promptPlaceholder: "[Start a new chat]"
95
+ openai:
96
+ randomizeUserId: false
97
+ captionSystemPrompt: ""
98
+ deepl:
99
+ formality: default
100
+ mistral:
101
+ enablePrefix: false
102
+ ollama:
103
+ keepAlive: -1
104
+ batchSize: -1
105
+ claude:
106
+ enableSystemPromptCache: false
107
+ cachingAtDepth: -1
108
+ enableServerPlugins: true
109
+ enableServerPluginsAutoUpdate: false
110
+ EOT
111
+
112
+ # Priority 2: Use CONFIG_YAML if provided (and username/password are not)
113
+ elif [ -n "${CONFIG_YAML}" ]; then
114
+ echo "--- Found CONFIG_YAML, creating config.yaml from environment variable. ---"
115
+ printf '%s\n' "${CONFIG_YAML}" > ${CONFIG_FILE}
116
+
117
+ # Priority 3: No config provided, let the app use its defaults
118
+ else
119
+ echo "--- No user/pass or CONFIG_YAML provided. App will use its default settings. ---"
120
+ fi
121
+
122
+ # --- BEGIN: Update SillyTavern Core at Runtime ---
123
+ echo '--- Attempting to update SillyTavern Core from GitHub (staging branch) ---'
124
+ if [ -d ".git" ] && [ "$(git rev-parse --abbrev-ref HEAD)" = "staging" ]; then
125
+ echo 'Existing staging branch found. Resetting and pulling latest changes...'
126
+ git reset --hard HEAD && \
127
+ git pull origin staging || echo 'WARN: git pull failed, continuing with code from build time.'
128
+ echo '--- SillyTavern Core update check finished. ---'
129
+ else
130
+ echo 'WARN: .git directory not found or not on staging branch. Skipping runtime update. Code from build time will be used.'
131
+ fi
132
+ # --- END: Update SillyTavern Core at Runtime ---
133
+
134
+ # --- BEGIN: Configure Git default identity at Runtime ---
135
+ echo '--- Configuring Git default user identity at runtime ---'
136
+ git config --global user.name "SillyTavern Sync" && \
137
+ git config --global user.email "sillytavern-sync@example.com" && \
138
+ git config --global --add safe.directory "${APP_HOME}/data"
139
+ echo '--- Git identity configured for runtime user. ---'
140
+ # --- END: Configure Git default identity at Runtime ---
141
+
142
+ # --- BEGIN: Dynamically Install Plugins at Runtime ---
143
+ echo '--- Checking for PLUGINS environment variable ---'
144
+ if [ -n "$PLUGINS" ]; then
145
+ echo "*** Installing Plugins specified in PLUGINS environment variable: $PLUGINS ***"
146
+ # Ensure plugins directory exists
147
+ mkdir -p ./plugins && chown node:node ./plugins
148
+ # Set comma as delimiter
149
+ IFS=','
150
+ # Loop through each plugin URL
151
+ for plugin_url in $PLUGINS; do
152
+ # Trim leading/trailing whitespace
153
+ plugin_url=$(echo "$plugin_url" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
154
+ if [ -z "$plugin_url" ]; then continue; fi
155
+ # Extract plugin name
156
+ plugin_name_git=$(basename "$plugin_url")
157
+ plugin_name=${plugin_name_git%.git}
158
+ plugin_dir="./plugins/$plugin_name"
159
+ echo "--- Installing plugin: $plugin_name from $plugin_url into $plugin_dir ---"
160
+ # Remove existing dir if it exists
161
+ rm -rf "$plugin_dir"
162
+ # Clone the plugin (run as root, fix perms later)
163
+ git clone --depth 1 "$plugin_url" "$plugin_dir"
164
+ if [ -f "$plugin_dir/package.json" ]; then
165
+ echo "--- Installing dependencies for $plugin_name ---"
166
+ (cd "$plugin_dir" && npm install --no-audit --no-fund --loglevel=error --no-progress --omit=dev --force && npm cache clean --force) || echo "WARN: Failed to install dependencies for $plugin_name"
167
+ else
168
+ echo "--- No package.json found for $plugin_name, skipping dependency install. ---"
169
+ fi || echo "WARN: Failed to clone $plugin_name from $plugin_url, skipping..."
170
+
171
+ # Configure cloud-saves plugin if this is the cloud-saves plugin
172
+ if [ "$plugin_name" = "cloud-saves" ]; then
173
+ echo "--- Detected cloud-saves plugin, checking for configuration environment variables ---"
174
+
175
+ # Set default values
176
+ REPO_URL_VALUE=${REPO_URL:-"https://github.com/fuwei99/sillytravern"}
177
+ GITHUB_TOKEN_VALUE=${GITHUB_TOKEN:-""}
178
+ AUTOSAVE_INTERVAL_VALUE=${AUTOSAVE_INTERVAL:-30}
179
+ AUTOSAVE_TARGET_TAG_VALUE=${AUTOSAVE_TARGET_TAG:-""}
180
+
181
+ # Always set autosave to false as required
182
+ AUTOSAVE_ENABLED="false"
183
+
184
+ echo "--- Creating cloud-saves plugin configuration file ---"
185
+ CONFIG_JSON_FILE="$plugin_dir/config.json"
186
+
187
+ # Generate config.json file
188
+ cat <<EOT > ${CONFIG_JSON_FILE}
189
+ {
190
+ "repo_url": "${REPO_URL_VALUE}",
191
+ "branch": "main",
192
+ "username": "cloud-saves",
193
+ "github_token": "${GITHUB_TOKEN_VALUE}",
194
+ "display_name": "",
195
+ "is_authorized": true,
196
+ "last_save": null,
197
+ "current_save": null,
198
+ "has_temp_stash": false,
199
+ "autoSaveEnabled": ${AUTOSAVE_ENABLED},
200
+ "autoSaveInterval": ${AUTOSAVE_INTERVAL_VALUE},
201
+ "autoSaveTargetTag": "${AUTOSAVE_TARGET_TAG_VALUE}"
202
+ }
203
+ EOT
204
+
205
+ # Set correct permissions for config file
206
+ chown node:node ${CONFIG_JSON_FILE}
207
+
208
+ echo "--- cloud-saves plugin configuration file created at: ${CONFIG_JSON_FILE} ---"
209
+ fi
210
+ done
211
+ # Reset IFS
212
+ unset IFS
213
+ # Fix permissions for plugins directory after installation
214
+ echo "--- Setting permissions for plugins directory ---"
215
+ chown -R node:node ./plugins
216
+ echo "*** Plugin installation finished. ***"
217
+ else
218
+ echo 'PLUGINS environment variable is not set or empty, skipping runtime plugin installation.'
219
+ fi
220
+ # --- END: Dynamically Install Plugins at Runtime ---
221
+
222
+ echo "*** Starting SillyTavern... ***"
223
+ node ${APP_HOME}/server.js &
224
+ SERVER_PID=$!
225
+
226
+ echo "SillyTavern server started with PID ${SERVER_PID}. Waiting for it to become responsive..."
227
+
228
+ # --- Health Check Logic ---
229
+ HEALTH_CHECK_URL="http://localhost:8000/"
230
+ CURL_COMMAND="curl -sf"
231
+
232
+ # If basic auth is enabled, provide credentials to curl for health checks
233
+ if [ -n "${USERNAME}" ] && [ -n "${PASSWORD}" ]; then
234
+ echo "--- Health check will use basic auth credentials. ---"
235
+ # The -u flag provides user:password for basic auth
236
+ CURL_COMMAND="curl -sf -u \"${USERNAME}:${PASSWORD}\""
237
+ fi
238
+
239
+ # Health check loop
240
+ RETRY_COUNT=0
241
+ MAX_RETRIES=12 # Wait for 60 seconds max
242
+ # Use eval to correctly execute the command string with quotes
243
+ while ! eval "${CURL_COMMAND} ${HEALTH_CHECK_URL}" > /dev/null; do
244
+ RETRY_COUNT=$((RETRY_COUNT+1))
245
+ if [ ${RETRY_COUNT} -ge ${MAX_RETRIES} ]; then
246
+ echo "SillyTavern failed to start. Exiting."
247
+ kill ${SERVER_PID}
248
+ exit 1
249
+ fi
250
+ echo "SillyTavern is still starting or not responsive on port 8000, waiting 5 seconds..."
251
+ sleep 5
252
+ done
253
+
254
+ echo "SillyTavern started successfully! Beginning periodic keep-alive..."
255
+
256
+ # --- BEGIN: Install Extensions after SillyTavern startup ---
257
+ install_extensions() {
258
+ echo "--- Waiting 40 seconds before installing extensions... ---"
259
+ sleep 40
260
+
261
+ echo "--- Checking for EXTENSIONS environment variable ---"
262
+ if [ -n "$EXTENSIONS" ]; then
263
+ echo "*** Installing Extensions specified in EXTENSIONS environment variable: $EXTENSIONS ***"
264
+
265
+ # Determine installation directory based on INSTALL_FOR_ALL_USERS
266
+ if [ "$INSTALL_FOR_ALL_USERS" = "true" ]; then
267
+ # System-level installation (for all users)
268
+ EXTENSIONS_DIR="./public/scripts/extensions/third-party"
269
+ echo "Installing extensions for all users in: $EXTENSIONS_DIR"
270
+ else
271
+ # User-level installation (for default user only)
272
+ EXTENSIONS_DIR="./data/default-user/extensions"
273
+ echo "Installing extensions for default user in: $EXTENSIONS_DIR"
274
+ fi
275
+
276
+ # Ensure extensions directory exists
277
+ mkdir -p "$EXTENSIONS_DIR" && chown node:node "$EXTENSIONS_DIR"
278
+
279
+ # Set comma as delimiter
280
+ IFS=','
281
+
282
+ # Loop through each extension URL
283
+ for extension_url in $EXTENSIONS; do
284
+ # Trim leading/trailing whitespace
285
+ extension_url=$(echo "$extension_url" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
286
+ if [ -z "$extension_url" ]; then continue; fi
287
+
288
+ # Extract extension name
289
+ extension_name_git=$(basename "$extension_url")
290
+ extension_name=${extension_name_git%.git}
291
+ extension_dir="$EXTENSIONS_DIR/$extension_name"
292
+
293
+ echo "--- Installing extension: $extension_name from $extension_url into $extension_dir ---"
294
+
295
+ # Remove existing dir if it exists
296
+ rm -rf "$extension_dir"
297
+
298
+ # Clone the extension
299
+ git clone --depth 1 "$extension_url" "$extension_dir"
300
+
301
+ # Check if extension has package.json and install dependencies if needed
302
+ if [ -f "$extension_dir/package.json" ]; then
303
+ echo "--- Installing dependencies for $extension_name ---"
304
+ (cd "$extension_dir" && npm install --no-audit --no-fund --loglevel=error --no-progress --omit=dev --force && npm cache clean --force) || echo "WARN: Failed to install dependencies for $extension_name"
305
+ else
306
+ echo "--- No package.json found for $extension_name, skipping dependency install. ---"
307
+ fi || echo "WARN: Failed to clone $extension_name from $extension_url, skipping..."
308
+ done
309
+
310
+ # Reset IFS
311
+ unset IFS
312
+
313
+ # Fix permissions for extensions directory after installation
314
+ echo "--- Setting permissions for extensions directory ---"
315
+ chown -R node:node "$EXTENSIONS_DIR"
316
+
317
+ echo "*** Extensions installation finished. ***"
318
+ else
319
+ echo 'EXTENSIONS environment variable is not set or empty, skipping extensions installation.'
320
+ fi
321
+ }
322
+
323
+ # Run the extension installation in the background
324
+ install_extensions &
325
+ # --- END: Install Extensions after SillyTavern startup ---
326
+
327
+ # Keep-alive loop
328
+ while kill -0 ${SERVER_PID} 2>/dev/null; do
329
+ echo "Sending keep-alive request to ${HEALTH_CHECK_URL}"
330
+ # Use eval here as well for the keep-alive command
331
+ eval "${CURL_COMMAND} ${HEALTH_CHECK_URL}" > /dev/null || echo "Keep-alive request failed."
332
+ echo "Keep-alive request sent. Sleeping for 30 minutes."
333
+ sleep 1800
334
+ done &
335
+
336
+ wait ${SERVER_PID}