mirror of
				https://github.com/SillyTavern/SillyTavern.git
				synced 2025-06-05 21:59:27 +02:00 
			
		
		
		
	Migrate to config.yaml
This commit is contained in:
		
							
								
								
									
										10
									
								
								.github/readme-zh_cn.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/readme-zh_cn.md
									
									
									
									
										vendored
									
									
								
							@@ -170,7 +170,7 @@ SillyTavern 会将 API 密钥保存在目录中的 `secrets.json` 文件内。
 | 
			
		||||
 | 
			
		||||
如果要想通过点击 API 输入框旁边的按钮来查看密钥,请按照以下设置:
 | 
			
		||||
 | 
			
		||||
1. 打开 `config.conf` 文件,将里面的 `allowKeysExposure` 设置为 `true`。
 | 
			
		||||
1. 打开 `config.yaml` 文件,将里面的 `allowKeysExposure` 设置为 `true`。
 | 
			
		||||
2. 然后重启 SillyTavern 服务。
 | 
			
		||||
 | 
			
		||||
## 远程访问
 | 
			
		||||
@@ -207,7 +207,7 @@ SillyTavern 会将 API 密钥保存在目录中的 `secrets.json` 文件内。
 | 
			
		||||
 | 
			
		||||
然后,文件中设置的 IP 就可以访问 SillyTavern 了。
 | 
			
		||||
 | 
			
		||||
*注意:"config.conf" 文件内也有一个 "whitelist" 设置,你可以用同样的方法设置它,但如果 "whitelist.txt" 文件存在,这个设置将被忽略。
 | 
			
		||||
*注意:"config.yaml" 文件内也有一个 "whitelist" 设置,你可以用同样的方法设置它,但如果 "whitelist.txt" 文件存在,这个设置将被忽略。
 | 
			
		||||
 | 
			
		||||
### 2.获取 SillyTavern 服务的 IP 地址
 | 
			
		||||
 | 
			
		||||
@@ -233,19 +233,19 @@ SillyTavern 会将 API 密钥保存在目录中的 `secrets.json` 文件内。
 | 
			
		||||
 | 
			
		||||
### 向所有 IP 开放您的 SillyTavern 服务
 | 
			
		||||
 | 
			
		||||
我们不建议这样做,但您可以打开 `config.conf` 并将里面的 `whitelist` 设置改为 `false`。
 | 
			
		||||
我们不建议这样做,但您可以打开 `config.yaml` 并将里面的 `whitelist` 设置改为 `false`。
 | 
			
		||||
 | 
			
		||||
你必须删除(或重命名)SillyTavern 文件夹中的 `whitelist.txt` 文件(如果有的话)。
 | 
			
		||||
 | 
			
		||||
这通常是不安全的做法,所以我们要求在这样做时必须设置用户名和密码。
 | 
			
		||||
 | 
			
		||||
用户名和密码在`config.conf`文件中设置。
 | 
			
		||||
用户名和密码在`config.yaml`文件中设置。
 | 
			
		||||
 | 
			
		||||
重启 SillyTavern 服务后,只要知道用户名和密码,任何设备都可以访问。
 | 
			
		||||
 | 
			
		||||
### 还是无法访问?
 | 
			
		||||
 | 
			
		||||
* 为 `config.conf` 文件中的端口创建一条入站/出站防火墙规则。切勿将此误认为是路由器上的端口转发,否则,有人可能会发现你的聊天隐私,那就大错特错了。
 | 
			
		||||
* 为 `config.yaml` 文件中的端口创建一条入站/出站防火墙规则。切勿将此误认为是路由器上的端口转发,否则,有人可能会发现你的聊天隐私,那就大错特错了。
 | 
			
		||||
* 在 "设置" > "网络和 Internet" > "以太网" 中启用 "专用网络" 配置。这对 Windows 11 非常重要,否则即使添加了上述防火墙规则也无法连接。
 | 
			
		||||
 | 
			
		||||
### 性能问题?
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								.github/readme.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/readme.md
									
									
									
									
										vendored
									
									
								
							@@ -173,7 +173,7 @@ By default, they will not be exposed to a frontend after you enter them and relo
 | 
			
		||||
 | 
			
		||||
In order to enable viewing your keys by clicking a button in the API block:
 | 
			
		||||
 | 
			
		||||
1. Set the value of `allowKeysExposure` to `true` in `config.conf` file.
 | 
			
		||||
1. Set the value of `allowKeysExposure` to `true` in `config.yaml` file.
 | 
			
		||||
2. Restart the SillyTavern server.
 | 
			
		||||
 | 
			
		||||
## Remote connections
 | 
			
		||||
@@ -211,7 +211,7 @@ CIDR masks are also accepted (eg. 10.0.0.0/24).
 | 
			
		||||
 | 
			
		||||
Now devices which have the IP specified in the file will be able to connect.
 | 
			
		||||
 | 
			
		||||
*Note: `config.conf` also has a `whitelist` array, which you can use in the same way, but this array will be ignored if `whitelist.txt` exists.*
 | 
			
		||||
*Note: `config.yaml` also has a `whitelist` array, which you can use in the same way, but this array will be ignored if `whitelist.txt` exists.*
 | 
			
		||||
 | 
			
		||||
### 2. Getting the IP for the ST host machine
 | 
			
		||||
 | 
			
		||||
@@ -237,19 +237,19 @@ Use http:// NOT https://
 | 
			
		||||
 | 
			
		||||
### Opening your ST to all IPs
 | 
			
		||||
 | 
			
		||||
We do not recommend doing this, but you can open `config.conf` and change `whitelist` to `false`.
 | 
			
		||||
We do not recommend doing this, but you can open `config.yaml` and change `whitelist` to `false`.
 | 
			
		||||
 | 
			
		||||
You must remove (or rename) `whitelist.txt` in the SillyTavern base install folder if it exists.
 | 
			
		||||
 | 
			
		||||
This is usually an insecure practice, so we require you to set a username and password when you do this.
 | 
			
		||||
 | 
			
		||||
The username and password are set in `config.conf`.
 | 
			
		||||
The username and password are set in `config.yaml`.
 | 
			
		||||
 | 
			
		||||
After restarting your ST server, any device will be able to connect to it, regardless of their IP as long as they know the username and password.
 | 
			
		||||
 | 
			
		||||
### Still Unable To Connect?
 | 
			
		||||
 | 
			
		||||
* Create an inbound/outbound firewall rule for the port found in `config.conf`. Do NOT mistake this for port-forwarding on your router, otherwise, someone could find your chat logs and that's a big no-no.
 | 
			
		||||
* Create an inbound/outbound firewall rule for the port found in `config.yaml`. Do NOT mistake this for port-forwarding on your router, otherwise, someone could find your chat logs and that's a big no-no.
 | 
			
		||||
* Enable the Private Network profile type in Settings > Network and Internet > Ethernet. This is VERY important for Windows 11, otherwise, you would be unable to connect even with the aforementioned firewall rules.
 | 
			
		||||
 | 
			
		||||
## Performance issues?
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -20,6 +20,8 @@ public/stats.json
 | 
			
		||||
/uploads/
 | 
			
		||||
*.jsonl
 | 
			
		||||
/config.conf
 | 
			
		||||
/config.yaml
 | 
			
		||||
/config.conf.bak
 | 
			
		||||
/docker/config
 | 
			
		||||
.DS_Store
 | 
			
		||||
public/settings.json
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@ RUN \
 | 
			
		||||
  echo "*** Create symbolic links to config directory ***" && \
 | 
			
		||||
  for R in $RESOURCES; do ln -s "../config/$R" "public/$R"; done || true && \
 | 
			
		||||
  \
 | 
			
		||||
  ln -s "./config/config.conf" "config.conf" || true && \
 | 
			
		||||
  ln -s "./config/config.yaml" "config.yaml" || true && \
 | 
			
		||||
  ln -s "../config/settings.json" "public/settings.json" || true && \
 | 
			
		||||
  ln -s "../../config/bg_load.css" "public/css/bg_load.css" || true && \
 | 
			
		||||
  mkdir "config" || true
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ echo WARNING: Cloudflare Tunnel!
 | 
			
		||||
echo ========================================================================================================================
 | 
			
		||||
echo This script downloads and runs the latest cloudflared.exe from Cloudflare to set up an HTTPS tunnel to your SillyTavern!
 | 
			
		||||
echo Using the randomly generated temporary tunnel URL, anyone can access your SillyTavern over the Internet while the tunnel
 | 
			
		||||
echo is active. Keep the URL safe and secure your SillyTavern installation by setting a username and password in config.conf!
 | 
			
		||||
echo is active. Keep the URL safe and secure your SillyTavern installation by setting a username and password in config.yaml!
 | 
			
		||||
echo.
 | 
			
		||||
echo See https://docs.sillytavern.app/usage/remoteconnections/ for more details about how to secure your SillyTavern install.
 | 
			
		||||
echo.
 | 
			
		||||
 
 | 
			
		||||
@@ -1,57 +0,0 @@
 | 
			
		||||
const port = 8000;
 | 
			
		||||
const whitelist = ['127.0.0.1']; //Example for add several IP in whitelist: ['127.0.0.1', '192.168.0.10']
 | 
			
		||||
const whitelistMode = true; //Disabling enabling the ip whitelist mode. true/false
 | 
			
		||||
const basicAuthMode = false; //Toggle basic authentication for endpoints.
 | 
			
		||||
const basicAuthUser = {username: "user", password: "password"}; //Login credentials when basicAuthMode is true.
 | 
			
		||||
const disableThumbnails = false; //Disables the generation of thumbnails, opting to use the raw images instead
 | 
			
		||||
const autorun = true; //Autorun in the browser. true/false
 | 
			
		||||
const enableExtensions = true; //Enables support for TavernAI-extras project
 | 
			
		||||
const listen = true; // If true, Can be access from other device or PC. otherwise can be access only from hosting machine.
 | 
			
		||||
const allowKeysExposure = false; // If true, private API keys could be fetched to the frontend.
 | 
			
		||||
const skipContentCheck = false; // If true, no new default content will be delivered to you.
 | 
			
		||||
const thumbnailsQuality = 95; // Quality of thumbnails. 0-100
 | 
			
		||||
const disableChatBackup = false; // Disables the backup of chat logs to the /backups folder
 | 
			
		||||
const enableCorsProxy = false; // Enables the CORS proxy for the frontend
 | 
			
		||||
 | 
			
		||||
// If true, Allows insecure settings for listen, whitelist, and authentication.
 | 
			
		||||
// Change this setting only on "trusted networks". Do not change this value unless you are aware of the issues that can arise from changing this setting and configuring a insecure setting.
 | 
			
		||||
const securityOverride = false;
 | 
			
		||||
 | 
			
		||||
// Additional settings for extra modules / extensions
 | 
			
		||||
const extras = {
 | 
			
		||||
    // Disables auto-download of models from the HuggingFace Hub.
 | 
			
		||||
    // You will need to manually download the models and put them into the /cache folder.
 | 
			
		||||
    disableAutoDownload: false,
 | 
			
		||||
    // Text classification model for sentiment analysis. HuggingFace ID of a model in ONNX format.
 | 
			
		||||
    classificationModel: 'Cohee/distilbert-base-uncased-go-emotions-onnx',
 | 
			
		||||
    // Image captioning model. HuggingFace ID of a model in ONNX format.
 | 
			
		||||
    captioningModel: 'Xenova/vit-gpt2-image-captioning',
 | 
			
		||||
    // Feature extraction model. HuggingFace ID of a model in ONNX format.
 | 
			
		||||
    embeddingModel: 'Xenova/all-mpnet-base-v2',
 | 
			
		||||
    // GPT-2 text generation model. HuggingFace ID of a model in ONNX format.
 | 
			
		||||
    promptExpansionModel: 'Cohee/fooocus_expansion-onnx',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Request overrides for additional headers
 | 
			
		||||
// Format is an array of objects:
 | 
			
		||||
// { hosts: [ "<url>" ], headers: { <header>: "<value>" } }
 | 
			
		||||
const requestOverrides = [];
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    port,
 | 
			
		||||
    whitelist,
 | 
			
		||||
    whitelistMode,
 | 
			
		||||
    basicAuthMode,
 | 
			
		||||
    basicAuthUser,
 | 
			
		||||
    autorun,
 | 
			
		||||
    enableExtensions,
 | 
			
		||||
    listen,
 | 
			
		||||
    disableThumbnails,
 | 
			
		||||
    allowKeysExposure,
 | 
			
		||||
    securityOverride,
 | 
			
		||||
    skipContentCheck,
 | 
			
		||||
    requestOverrides,
 | 
			
		||||
    thumbnailsQuality,
 | 
			
		||||
    extras,
 | 
			
		||||
    disableChatBackup,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										53
									
								
								default/config.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								default/config.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
# -- NETWORK CONFIGURATION --
 | 
			
		||||
# Listen for incoming connections
 | 
			
		||||
listen: true
 | 
			
		||||
# Server port
 | 
			
		||||
port: 8000
 | 
			
		||||
# Toggle whitelist mode
 | 
			
		||||
whitelistMode: true
 | 
			
		||||
# Whitelist of allowed IP addresses
 | 
			
		||||
whitelist:
 | 
			
		||||
  - 127.0.0.1
 | 
			
		||||
# Toggle basic authentication for endpoints
 | 
			
		||||
basicAuthMode: false
 | 
			
		||||
# Basic authentication credentials
 | 
			
		||||
basicAuthUser:
 | 
			
		||||
  username: user
 | 
			
		||||
  password: password
 | 
			
		||||
# Enables CORS proxy middleware
 | 
			
		||||
enableCorsProxy: false
 | 
			
		||||
# Disable security checks - NOT RECOMMENDED
 | 
			
		||||
securityOverride: false
 | 
			
		||||
# -- ADVANCED CONFIGURATION --
 | 
			
		||||
# Open the browser automatically
 | 
			
		||||
autorun: true
 | 
			
		||||
# Disable thumbnail generation
 | 
			
		||||
disableThumbnails: false
 | 
			
		||||
# Thumbnail quality (0-100)
 | 
			
		||||
thumbnailsQuality: 95
 | 
			
		||||
# Allow secret keys exposure via API
 | 
			
		||||
allowKeysExposure: false
 | 
			
		||||
# Skip new default content checks
 | 
			
		||||
skipContentCheck: false
 | 
			
		||||
# Disable automatic chats backup
 | 
			
		||||
disableChatBackup: false
 | 
			
		||||
# API request overrides (for KoboldAI and Text Completion APIs)
 | 
			
		||||
## Format is an array of objects:
 | 
			
		||||
## - hosts:
 | 
			
		||||
##   - example.com
 | 
			
		||||
##   headers:
 | 
			
		||||
##     Content-Type: application/json
 | 
			
		||||
requestOverrides: []
 | 
			
		||||
# -- PLUGIN CONFIGURATION --
 | 
			
		||||
# Enable UI extensions
 | 
			
		||||
enableExtensions: true
 | 
			
		||||
# Extension settings
 | 
			
		||||
extras:
 | 
			
		||||
  # Disables automatic model download from HuggingFace
 | 
			
		||||
  disableAutoDownload: false
 | 
			
		||||
  # Extra models for plugins. Expects model IDs from HuggingFace model hub in ONNX format
 | 
			
		||||
  classificationModel: Cohee/distilbert-base-uncased-go-emotions-onnx
 | 
			
		||||
  captioningModel: Xenova/vit-gpt2-image-captioning
 | 
			
		||||
  embeddingModel: Xenova/all-mpnet-base-v2
 | 
			
		||||
  promptExpansionModel: Cohee/fooocus_expansion-onnx
 | 
			
		||||
 | 
			
		||||
@@ -9,9 +9,9 @@ for R in $RESOURCES; do
 | 
			
		||||
  fi
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
if [ ! -e "config/config.conf" ]; then
 | 
			
		||||
    echo "Resource not found, copying from defaults: config.conf"
 | 
			
		||||
    cp -r "default/config.conf" "config/config.conf"
 | 
			
		||||
if [ ! -e "config/config.yaml" ]; then
 | 
			
		||||
    echo "Resource not found, copying from defaults: config.yaml"
 | 
			
		||||
    cp -r "default/config.yaml" "config/config.yaml"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ ! -e "config/settings.json" ]; then
 | 
			
		||||
@@ -24,15 +24,15 @@ if [ ! -e "config/bg_load.css" ]; then
 | 
			
		||||
    cp -r "default/bg_load.css" "config/bg_load.css"
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
CONFIG_FILE="config.conf"
 | 
			
		||||
CONFIG_FILE="config.yaml"
 | 
			
		||||
 | 
			
		||||
if grep -q "listen = false" $CONFIG_FILE; then
 | 
			
		||||
  echo -e "\033[1;31mThe listen parameter is set to false. If you can't connect to the server, edit the \"docker/config/config.conf\" file and restart the container.\033[0m"
 | 
			
		||||
if grep -q "listen: false" $CONFIG_FILE; then
 | 
			
		||||
  echo -e "\033[1;31mThe listen parameter is set to false. If you can't connect to the server, edit the \"docker/config/config.yaml\" file and restart the container.\033[0m"
 | 
			
		||||
  sleep 5
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if grep -q "whitelistMode = true" $CONFIG_FILE; then
 | 
			
		||||
  echo -e "\033[1;31mThe whitelistMode parameter is set to true. If you can't connect to the server, edit the \"docker/config/config.conf\" file and restart the container.\033[0m"
 | 
			
		||||
if grep -q "whitelistMode: true" $CONFIG_FILE; then
 | 
			
		||||
  echo -e "\033[1;31mThe whitelistMode parameter is set to true. If you can't connect to the server, edit the \"docker/config/config.yaml\" file and restart the container.\033[0m"
 | 
			
		||||
  sleep 5
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -43,6 +43,7 @@
 | 
			
		||||
                "vectra": "^0.2.2",
 | 
			
		||||
                "write-file-atomic": "^5.0.1",
 | 
			
		||||
                "ws": "^8.13.0",
 | 
			
		||||
                "yaml": "^2.3.4",
 | 
			
		||||
                "yargs": "^17.7.1",
 | 
			
		||||
                "yauzl": "^2.10.0"
 | 
			
		||||
            },
 | 
			
		||||
@@ -4388,6 +4389,14 @@
 | 
			
		||||
            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
			
		||||
            "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/yaml": {
 | 
			
		||||
            "version": "2.3.4",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
 | 
			
		||||
            "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
 | 
			
		||||
            "engines": {
 | 
			
		||||
                "node": ">= 14"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "node_modules/yargs": {
 | 
			
		||||
            "version": "17.7.2",
 | 
			
		||||
            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,7 @@
 | 
			
		||||
        "vectra": "^0.2.2",
 | 
			
		||||
        "write-file-atomic": "^5.0.1",
 | 
			
		||||
        "ws": "^8.13.0",
 | 
			
		||||
        "yaml": "^2.3.4",
 | 
			
		||||
        "yargs": "^17.7.1",
 | 
			
		||||
        "yauzl": "^2.10.0"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										106
									
								
								post-install.js
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								post-install.js
									
									
									
									
									
								
							@@ -4,6 +4,102 @@
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const crypto = require('crypto');
 | 
			
		||||
const yaml = require('yaml');
 | 
			
		||||
const _ = require('lodash');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Colorizes console output.
 | 
			
		||||
 */
 | 
			
		||||
const color = {
 | 
			
		||||
    byNum: (mess, fgNum) => {
 | 
			
		||||
        mess = mess || '';
 | 
			
		||||
        fgNum = fgNum === undefined ? 31 : fgNum;
 | 
			
		||||
        return '\u001b[' + fgNum + 'm' + mess + '\u001b[39m';
 | 
			
		||||
    },
 | 
			
		||||
    black: (mess) => color.byNum(mess, 30),
 | 
			
		||||
    red: (mess) => color.byNum(mess, 31),
 | 
			
		||||
    green: (mess) => color.byNum(mess, 32),
 | 
			
		||||
    yellow: (mess) => color.byNum(mess, 33),
 | 
			
		||||
    blue: (mess) => color.byNum(mess, 34),
 | 
			
		||||
    magenta: (mess) => color.byNum(mess, 35),
 | 
			
		||||
    cyan: (mess) => color.byNum(mess, 36),
 | 
			
		||||
    white: (mess) => color.byNum(mess, 37)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Gets all keys from an object recursively.
 | 
			
		||||
 * @param {object} obj Object to get all keys from
 | 
			
		||||
 * @param {string} prefix Prefix to prepend to all keys
 | 
			
		||||
 * @returns {string[]} Array of all keys in the object
 | 
			
		||||
 */
 | 
			
		||||
function getAllKeys(obj, prefix = '') {
 | 
			
		||||
    if (typeof obj !== 'object' || Array.isArray(obj)) {
 | 
			
		||||
        return [];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return _.flatMap(Object.keys(obj), key => {
 | 
			
		||||
        const newPrefix = prefix ? `${prefix}.${key}` : key;
 | 
			
		||||
        if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
 | 
			
		||||
            return getAllKeys(obj[key], newPrefix);
 | 
			
		||||
        } else {
 | 
			
		||||
            return [newPrefix];
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Converts the old config.conf file to the new config.yaml format.
 | 
			
		||||
 */
 | 
			
		||||
function convertConfig() {
 | 
			
		||||
    if (fs.existsSync('./config.conf')) {
 | 
			
		||||
        if (fs.existsSync('./config.yaml')) {
 | 
			
		||||
            console.log(color.yellow('Both config.conf and config.yaml exist. Please delete config.conf manually.'));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            console.log(color.blue('Converting config.conf to config.yaml. Your old config.conf will be renamed to config.conf.bak'));
 | 
			
		||||
            const config = require(path.join(process.cwd(), './config.conf'));
 | 
			
		||||
            fs.renameSync('./config.conf', './config.conf.bak');
 | 
			
		||||
            fs.writeFileSync('./config.yaml', yaml.stringify(config));
 | 
			
		||||
            console.log(color.green('Conversion successful. Please check your config.yaml and fix it if necessary.'));
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error(color.red('FATAL: Config conversion failed. Please check your config.conf file and try again.'));
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Compares the current config.yaml with the default config.yaml and adds any missing values.
 | 
			
		||||
 */
 | 
			
		||||
function addMissingConfigValues() {
 | 
			
		||||
    try  {
 | 
			
		||||
        const defaultConfig = yaml.parse(fs.readFileSync(path.join(process.cwd(), './default/config.yaml'), 'utf8'));
 | 
			
		||||
        let config = yaml.parse(fs.readFileSync(path.join(process.cwd(), './config.yaml'), 'utf8'));
 | 
			
		||||
 | 
			
		||||
        // Get all keys from the original config
 | 
			
		||||
        const originalKeys = getAllKeys(config);
 | 
			
		||||
 | 
			
		||||
        // Use lodash's defaultsDeep function to recursively apply default properties
 | 
			
		||||
        config = _.defaultsDeep(config, defaultConfig);
 | 
			
		||||
 | 
			
		||||
        // Get all keys from the updated config
 | 
			
		||||
        const updatedKeys = getAllKeys(config);
 | 
			
		||||
 | 
			
		||||
        // Find the keys that were added
 | 
			
		||||
        const addedKeys = _.difference(updatedKeys, originalKeys);
 | 
			
		||||
 | 
			
		||||
        if (addedKeys.length === 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        console.log('Adding missing config values to config.yaml:', addedKeys);
 | 
			
		||||
        fs.writeFileSync('./config.yaml', yaml.stringify(config));
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.error(color.red('FATAL: Could not add missing config values to config.yaml'), error);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates the default config files if they don't exist yet.
 | 
			
		||||
@@ -12,7 +108,7 @@ function createDefaultFiles() {
 | 
			
		||||
    const files = {
 | 
			
		||||
        settings: './public/settings.json',
 | 
			
		||||
        bg_load: './public/css/bg_load.css',
 | 
			
		||||
        config: './config.conf',
 | 
			
		||||
        config: './config.yaml',
 | 
			
		||||
        user: './public/css/user.css',
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -21,10 +117,10 @@ function createDefaultFiles() {
 | 
			
		||||
            if (!fs.existsSync(file)) {
 | 
			
		||||
                const defaultFilePath = path.join('./default', path.parse(file).base);
 | 
			
		||||
                fs.copyFileSync(defaultFilePath, file);
 | 
			
		||||
                console.log(`Created default file: ${file}`);
 | 
			
		||||
                console.log(color.green(`Created default file: ${file}`));
 | 
			
		||||
            }
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.error(`FATAL: Could not write default file: ${file}`, error);
 | 
			
		||||
            console.error(color.red(`FATAL: Could not write default file: ${file}`), error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -73,10 +169,14 @@ function copyWasmFiles() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
try {
 | 
			
		||||
    // 0. Convert config.conf to config.yaml
 | 
			
		||||
    convertConfig();
 | 
			
		||||
    // 1. Create default config files
 | 
			
		||||
    createDefaultFiles();
 | 
			
		||||
    // 2. Copy transformers WASM binaries from node_modules
 | 
			
		||||
    copyWasmFiles();
 | 
			
		||||
    // 3. Add missing config values
 | 
			
		||||
    addMissingConfigValues();
 | 
			
		||||
} catch (error) {
 | 
			
		||||
    console.error(error);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -55,7 +55,7 @@ async function viewSecrets() {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (response.status == 403) {
 | 
			
		||||
        callPopup('<h3>Forbidden</h3><p>To view your API keys here, set the value of allowKeysExposure to true in config.conf file and restart the SillyTavern server.</p>', 'text');
 | 
			
		||||
        callPopup('<h3>Forbidden</h3><p>To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.</p>', 'text');
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								server.js
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								server.js
									
									
									
									
									
								
							@@ -55,7 +55,7 @@ const characterCardParser = require('./src/character-card-parser.js');
 | 
			
		||||
const contentManager = require('./src/content-manager');
 | 
			
		||||
const statsHelpers = require('./statsHelpers.js');
 | 
			
		||||
const { readSecret, migrateSecrets, SECRET_KEYS } = require('./src/secrets');
 | 
			
		||||
const { delay, getVersion, deepMerge } = require('./src/util');
 | 
			
		||||
const { delay, getVersion, deepMerge, getConfigValue, color } = require('./src/util');
 | 
			
		||||
const { invalidateThumbnail, ensureThumbnailCache } = require('./src/thumbnails');
 | 
			
		||||
const { getTokenizerModel, getTiktokenTokenizer, loadTokenizers, TEXT_COMPLETION_MODELS, getSentencepiceTokenizer, sentencepieceTokenizers } = require('./src/tokenizers');
 | 
			
		||||
const { convertClaudePrompt } = require('./src/chat-completion');
 | 
			
		||||
@@ -109,12 +109,10 @@ app.use(responseTime());
 | 
			
		||||
 | 
			
		||||
// impoort from statsHelpers.js
 | 
			
		||||
 | 
			
		||||
const config = require(path.join(process.cwd(), './config.conf'));
 | 
			
		||||
 | 
			
		||||
const server_port = process.env.SILLY_TAVERN_PORT || config.port;
 | 
			
		||||
const server_port = process.env.SILLY_TAVERN_PORT || getConfigValue('port');
 | 
			
		||||
 | 
			
		||||
const whitelistPath = path.join(process.cwd(), "./whitelist.txt");
 | 
			
		||||
let whitelist = config.whitelist;
 | 
			
		||||
let whitelist = getConfigValue('whitelist', []);
 | 
			
		||||
 | 
			
		||||
if (fs.existsSync(whitelistPath)) {
 | 
			
		||||
    try {
 | 
			
		||||
@@ -123,10 +121,10 @@ if (fs.existsSync(whitelistPath)) {
 | 
			
		||||
    } catch (e) { }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const whitelistMode = config.whitelistMode;
 | 
			
		||||
const autorun = config.autorun && cliArguments.autorun !== false && !cliArguments.ssl;
 | 
			
		||||
const enableExtensions = config.enableExtensions;
 | 
			
		||||
const listen = config.listen;
 | 
			
		||||
const whitelistMode = getConfigValue('whitelistMode', true);
 | 
			
		||||
const autorun = getConfigValue('autorun') && cliArguments.autorun !== false && !cliArguments.ssl;
 | 
			
		||||
const enableExtensions = getConfigValue('enableExtensions', true);
 | 
			
		||||
const listen = getConfigValue('listen', false);
 | 
			
		||||
 | 
			
		||||
const API_OPENAI = "https://api.openai.com/v1";
 | 
			
		||||
const API_CLAUDE = "https://api.anthropic.com/v1";
 | 
			
		||||
@@ -138,22 +136,6 @@ let main_api = "kobold";
 | 
			
		||||
let characters = {};
 | 
			
		||||
let response_dw_bg;
 | 
			
		||||
 | 
			
		||||
let color = {
 | 
			
		||||
    byNum: (mess, fgNum) => {
 | 
			
		||||
        mess = mess || '';
 | 
			
		||||
        fgNum = fgNum === undefined ? 31 : fgNum;
 | 
			
		||||
        return '\u001b[' + fgNum + 'm' + mess + '\u001b[39m';
 | 
			
		||||
    },
 | 
			
		||||
    black: (mess) => color.byNum(mess, 30),
 | 
			
		||||
    red: (mess) => color.byNum(mess, 31),
 | 
			
		||||
    green: (mess) => color.byNum(mess, 32),
 | 
			
		||||
    yellow: (mess) => color.byNum(mess, 33),
 | 
			
		||||
    blue: (mess) => color.byNum(mess, 34),
 | 
			
		||||
    magenta: (mess) => color.byNum(mess, 35),
 | 
			
		||||
    cyan: (mess) => color.byNum(mess, 36),
 | 
			
		||||
    white: (mess) => color.byNum(mess, 37)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function getMancerHeaders() {
 | 
			
		||||
    const apiKey = readSecret(SECRET_KEYS.MANCER);
 | 
			
		||||
 | 
			
		||||
@@ -182,7 +164,8 @@ function getTabbyHeaders() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getOverrideHeaders(urlHost) {
 | 
			
		||||
    const overrideHeaders = config.requestOverrides?.find((e) => e.hosts?.includes(urlHost))?.headers;
 | 
			
		||||
    const requestOverrides = getConfigValue('requestOverrides', []);
 | 
			
		||||
    const overrideHeaders = requestOverrides?.find((e) => e.hosts?.includes(urlHost))?.headers;
 | 
			
		||||
    if (overrideHeaders && urlHost) {
 | 
			
		||||
        return overrideHeaders;
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -277,7 +260,7 @@ const CORS = cors({
 | 
			
		||||
 | 
			
		||||
app.use(CORS);
 | 
			
		||||
 | 
			
		||||
if (listen && config.basicAuthMode) app.use(basicAuthMiddleware);
 | 
			
		||||
if (listen && getConfigValue('basicAuthMode', false)) app.use(basicAuthMiddleware);
 | 
			
		||||
 | 
			
		||||
// IP Whitelist //
 | 
			
		||||
let knownIPs = new Set();
 | 
			
		||||
@@ -316,13 +299,13 @@ app.use(function (req, res, next) {
 | 
			
		||||
 | 
			
		||||
    //clientIp = req.connection.remoteAddress.split(':').pop();
 | 
			
		||||
    if (whitelistMode === true && !whitelist.some(x => ipMatching.matches(clientIp, ipMatching.getMatch(x)))) {
 | 
			
		||||
        console.log(color.red('Forbidden: Connection attempt from ' + clientIp + '. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of SillyTavern folder.\n'));
 | 
			
		||||
        return res.status(403).send('<b>Forbidden</b>: Connection attempt from <b>' + clientIp + '</b>. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.conf in root of SillyTavern folder.');
 | 
			
		||||
        console.log(color.red('Forbidden: Connection attempt from ' + clientIp + '. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.yaml in root of SillyTavern folder.\n'));
 | 
			
		||||
        return res.status(403).send('<b>Forbidden</b>: Connection attempt from <b>' + clientIp + '</b>. If you are attempting to connect, please add your IP address in whitelist or disable whitelist mode in config.yaml in root of SillyTavern folder.');
 | 
			
		||||
    }
 | 
			
		||||
    next();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
if (config.enableCorsProxy === true || cliArguments.corsProxy === true) {
 | 
			
		||||
if (getConfigValue('enableCorsProxy', false) === true || cliArguments.corsProxy === true) {
 | 
			
		||||
    console.log('Enabling CORS proxy');
 | 
			
		||||
 | 
			
		||||
    app.use('/proxy/:url', async (req, res) => {
 | 
			
		||||
@@ -3670,12 +3653,12 @@ const setupTasks = async function () {
 | 
			
		||||
    console.log(color.green('SillyTavern is listening on: ' + tavernUrl));
 | 
			
		||||
 | 
			
		||||
    if (listen) {
 | 
			
		||||
        console.log('\n0.0.0.0 means SillyTavern is listening on all network interfaces (Wi-Fi, LAN, localhost). If you want to limit it only to internal localhost (127.0.0.1), change the setting in config.conf to "listen=false". Check "access.log" file in the SillyTavern directory if you want to inspect incoming connections.\n');
 | 
			
		||||
        console.log('\n0.0.0.0 means SillyTavern is listening on all network interfaces (Wi-Fi, LAN, localhost). If you want to limit it only to internal localhost (127.0.0.1), change the setting in config.yaml to "listen: false". Check "access.log" file in the SillyTavern directory if you want to inspect incoming connections.\n');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
if (listen && !config.whitelistMode && !config.basicAuthMode) {
 | 
			
		||||
    if (config.securityOverride) {
 | 
			
		||||
if (listen && !getConfigValue('whitelistMode', true) && !getConfigValue('basicAuthMode', false)) {
 | 
			
		||||
    if (getConfigValue('securityOverride', false)) {
 | 
			
		||||
        console.warn(color.red("Security has been overridden. If it's not a trusted network, change the settings."));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
@@ -3722,7 +3705,7 @@ function generateTimestamp() {
 | 
			
		||||
 */
 | 
			
		||||
function backupChat(name, chat) {
 | 
			
		||||
    try {
 | 
			
		||||
        const isBackupDisabled = config.disableChatBackup;
 | 
			
		||||
        const isBackupDisabled = getConfigValue('disableChatBackup', false);
 | 
			
		||||
 | 
			
		||||
        if (isBackupDisabled) {
 | 
			
		||||
            return;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,14 +2,14 @@ const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const fetch = require('node-fetch').default;
 | 
			
		||||
const sanitize = require('sanitize-filename');
 | 
			
		||||
const config = require(path.join(process.cwd(), './config.conf'));
 | 
			
		||||
const { getConfigValue } = require('./util');
 | 
			
		||||
const contentDirectory = path.join(process.cwd(), 'default/content');
 | 
			
		||||
const contentLogPath = path.join(contentDirectory, 'content.log');
 | 
			
		||||
const contentIndexPath = path.join(contentDirectory, 'index.json');
 | 
			
		||||
 | 
			
		||||
function checkForNewContent() {
 | 
			
		||||
    try {
 | 
			
		||||
        if (config.skipContentCheck) {
 | 
			
		||||
        if (getConfigValue('skipContentCheck', false)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -173,7 +173,7 @@ function registerEndpoints(app, jsonParser) {
 | 
			
		||||
        const allowKeysExposure = getConfigValue('allowKeysExposure', false);
 | 
			
		||||
 | 
			
		||||
        if (!allowKeysExposure) {
 | 
			
		||||
            console.error('secrets.json could not be viewed unless the value of allowKeysExposure in config.conf is set to true');
 | 
			
		||||
            console.error('secrets.json could not be viewed unless the value of allowKeysExposure in config.yaml is set to true');
 | 
			
		||||
            return response.sendStatus(403);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -195,7 +195,7 @@ function registerEndpoints(app, jsonParser) {
 | 
			
		||||
        const allowKeysExposure = getConfigValue('allowKeysExposure', false);
 | 
			
		||||
 | 
			
		||||
        if (!allowKeysExposure) {
 | 
			
		||||
            console.error('Cannot fetch secrets unless allowKeysExposure in config.conf is set to true');
 | 
			
		||||
            console.error('Cannot fetch secrets unless allowKeysExposure in config.yaml is set to true');
 | 
			
		||||
            return response.sendStatus(403);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ function getModelForTask(task) {
 | 
			
		||||
        const model = getConfigValue(tasks[task].configField, null);
 | 
			
		||||
        return model || defaultModel;
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.warn('Failed to read config.conf, using default classification model.');
 | 
			
		||||
        console.warn('Failed to read config.yaml, using default classification model.');
 | 
			
		||||
        return defaultModel;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										57
									
								
								src/util.js
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								src/util.js
									
									
									
									
									
								
							@@ -4,20 +4,46 @@ const commandExistsSync = require('command-exists').sync;
 | 
			
		||||
const _ = require('lodash');
 | 
			
		||||
const yauzl = require('yauzl');
 | 
			
		||||
const mime = require('mime-types');
 | 
			
		||||
const yaml = require('yaml');
 | 
			
		||||
const { default: simpleGit } = require('simple-git');
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Returns the config object from the config.conf file.
 | 
			
		||||
 * Returns the config object from the config.yaml file.
 | 
			
		||||
 * @returns {object} Config object
 | 
			
		||||
 */
 | 
			
		||||
function getConfig() {
 | 
			
		||||
    try {
 | 
			
		||||
        const config = require(path.join(process.cwd(), './config.conf'));
 | 
			
		||||
        return config;
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
        console.warn('Failed to read config.conf');
 | 
			
		||||
        return {};
 | 
			
		||||
    function getNewConfig() {
 | 
			
		||||
        try {
 | 
			
		||||
            const config = yaml.parse(fs.readFileSync(path.join(process.cwd(), './config.yaml'), 'utf8'));
 | 
			
		||||
            return config;
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.warn('Failed to read config.yaml');
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getLegacyConfig() {
 | 
			
		||||
        try {
 | 
			
		||||
            console.log(color.yellow('WARNING: config.conf is deprecated. Please run "npm run postinstall" to convert to config.yaml'));
 | 
			
		||||
            const config = require(path.join(process.cwd(), './config.conf'));
 | 
			
		||||
            return config;
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.warn('Failed to read config.conf');
 | 
			
		||||
            return {};
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fs.existsSync('./config.yaml')) {
 | 
			
		||||
        return getNewConfig();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fs.existsSync('./config.conf')) {
 | 
			
		||||
        return getLegacyConfig();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    console.error(color.red('No config file found. Please create a config.yaml file. The default config file can be found in the /default folder.'));
 | 
			
		||||
    console.error(color.red('The program will now exit.'));
 | 
			
		||||
    process.exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -217,6 +243,22 @@ function deepMerge(target, source) {
 | 
			
		||||
    return output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const color = {
 | 
			
		||||
    byNum: (mess, fgNum) => {
 | 
			
		||||
        mess = mess || '';
 | 
			
		||||
        fgNum = fgNum === undefined ? 31 : fgNum;
 | 
			
		||||
        return '\u001b[' + fgNum + 'm' + mess + '\u001b[39m';
 | 
			
		||||
    },
 | 
			
		||||
    black: (mess) => color.byNum(mess, 30),
 | 
			
		||||
    red: (mess) => color.byNum(mess, 31),
 | 
			
		||||
    green: (mess) => color.byNum(mess, 32),
 | 
			
		||||
    yellow: (mess) => color.byNum(mess, 33),
 | 
			
		||||
    blue: (mess) => color.byNum(mess, 34),
 | 
			
		||||
    magenta: (mess) => color.byNum(mess, 35),
 | 
			
		||||
    cyan: (mess) => color.byNum(mess, 36),
 | 
			
		||||
    white: (mess) => color.byNum(mess, 37)
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getConfig,
 | 
			
		||||
    getConfigValue,
 | 
			
		||||
@@ -227,4 +269,5 @@ module.exports = {
 | 
			
		||||
    readAllChunks,
 | 
			
		||||
    delay,
 | 
			
		||||
    deepMerge,
 | 
			
		||||
    color,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user