mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Move config migration from post-install to src
This commit is contained in:
1
.github/readme.md
vendored
1
.github/readme.md
vendored
@ -350,6 +350,7 @@ Start.bat --port 8000 --listen false
|
|||||||
| Option | Description | Type |
|
| Option | Description | Type |
|
||||||
|-------------------------|----------------------------------------------------------------------|----------|
|
|-------------------------|----------------------------------------------------------------------|----------|
|
||||||
| `--version` | Show version number | boolean |
|
| `--version` | Show version number | boolean |
|
||||||
|
| `--configPath` | Override the path to the config.yaml file | string |
|
||||||
| `--dataRoot` | Root directory for data storage | string |
|
| `--dataRoot` | Root directory for data storage | string |
|
||||||
| `--port` | Sets the port under which SillyTavern will run | number |
|
| `--port` | Sets the port under which SillyTavern will run | number |
|
||||||
| `--listen` | SillyTavern will listen on all network interfaces | boolean |
|
| `--listen` | SillyTavern will listen on all network interfaces | boolean |
|
||||||
|
184
post-install.js
184
post-install.js
@ -5,130 +5,15 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import process from 'node:process';
|
import process from 'node:process';
|
||||||
import yaml from 'yaml';
|
import yaml from 'yaml';
|
||||||
import _ from 'lodash';
|
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { createRequire } from 'node:module';
|
import { createRequire } from 'node:module';
|
||||||
|
import { addMissingConfigValues } from './src/config-init.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Colorizes console output.
|
* Colorizes console output.
|
||||||
*/
|
*/
|
||||||
const color = chalk;
|
const color = chalk;
|
||||||
|
|
||||||
const keyMigrationMap = [
|
|
||||||
{
|
|
||||||
oldKey: 'disableThumbnails',
|
|
||||||
newKey: 'thumbnails.enabled',
|
|
||||||
migrate: (value) => !value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'thumbnailsQuality',
|
|
||||||
newKey: 'thumbnails.quality',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'avatarThumbnailsPng',
|
|
||||||
newKey: 'thumbnails.format',
|
|
||||||
migrate: (value) => (value ? 'png' : 'jpg'),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'disableChatBackup',
|
|
||||||
newKey: 'backups.chat.enabled',
|
|
||||||
migrate: (value) => !value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'numberOfBackups',
|
|
||||||
newKey: 'backups.common.numberOfBackups',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'maxTotalChatBackups',
|
|
||||||
newKey: 'backups.chat.maxTotalBackups',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'chatBackupThrottleInterval',
|
|
||||||
newKey: 'backups.chat.throttleInterval',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'enableExtensions',
|
|
||||||
newKey: 'extensions.enabled',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'enableExtensionsAutoUpdate',
|
|
||||||
newKey: 'extensions.autoUpdate',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.disableAutoDownload',
|
|
||||||
newKey: 'extensions.models.autoDownload',
|
|
||||||
migrate: (value) => !value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.classificationModel',
|
|
||||||
newKey: 'extensions.models.classification',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.captioningModel',
|
|
||||||
newKey: 'extensions.models.captioning',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.embeddingModel',
|
|
||||||
newKey: 'extensions.models.embedding',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.speechToTextModel',
|
|
||||||
newKey: 'extensions.models.speechToText',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'extras.textToSpeechModel',
|
|
||||||
newKey: 'extensions.models.textToSpeech',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'minLogLevel',
|
|
||||||
newKey: 'logging.minLogLevel',
|
|
||||||
migrate: (value) => value,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'cardsCacheCapacity',
|
|
||||||
newKey: 'performance.memoryCacheCapacity',
|
|
||||||
migrate: (value) => `${value}mb`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
oldKey: 'cookieSecret',
|
|
||||||
newKey: 'cookieSecret',
|
|
||||||
migrate: () => void 0,
|
|
||||||
remove: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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) || obj === null) {
|
|
||||||
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.
|
* Converts the old config.conf file to the new config.yaml format.
|
||||||
*/
|
*/
|
||||||
@ -155,71 +40,6 @@ function convertConfig() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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'));
|
|
||||||
|
|
||||||
// Migrate old keys to new keys
|
|
||||||
const migratedKeys = [];
|
|
||||||
for (const { oldKey, newKey, migrate, remove } of keyMigrationMap) {
|
|
||||||
if (_.has(config, oldKey)) {
|
|
||||||
if (remove) {
|
|
||||||
_.unset(config, oldKey);
|
|
||||||
migratedKeys.push({
|
|
||||||
oldKey,
|
|
||||||
newValue: void 0,
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const oldValue = _.get(config, oldKey);
|
|
||||||
const newValue = migrate(oldValue);
|
|
||||||
_.set(config, newKey, newValue);
|
|
||||||
_.unset(config, oldKey);
|
|
||||||
|
|
||||||
migratedKeys.push({
|
|
||||||
oldKey,
|
|
||||||
newKey,
|
|
||||||
oldValue,
|
|
||||||
newValue,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 && migratedKeys.length === 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedKeys.length > 0) {
|
|
||||||
console.log('Adding missing config values to config.yaml:', addedKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (migratedKeys.length > 0) {
|
|
||||||
console.log('Migrating config values in config.yaml:', migratedKeys);
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
* Creates the default config files if they don't exist yet.
|
||||||
*/
|
*/
|
||||||
@ -288,7 +108,7 @@ try {
|
|||||||
// 1. Create default config files
|
// 1. Create default config files
|
||||||
createDefaultFiles();
|
createDefaultFiles();
|
||||||
// 2. Add missing config values
|
// 2. Add missing config values
|
||||||
addMissingConfigValues();
|
addMissingConfigValues(path.join(process.cwd(), './config.yaml'));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import yargs from 'yargs/yargs';
|
import yargs from 'yargs/yargs';
|
||||||
import { hideBin } from 'yargs/helpers';
|
import { hideBin } from 'yargs/helpers';
|
||||||
import ipRegex from 'ip-regex';
|
import ipRegex from 'ip-regex';
|
||||||
import { canResolve, color, getConfigValue, setConfigFilePath, stringToBool } from './util.js';
|
import { canResolve, color, getConfigValue, stringToBool } from './util.js';
|
||||||
|
import { initConfig } from './config-init.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} CommandLineArguments Parsed command line arguments
|
* @typedef {object} CommandLineArguments Parsed command line arguments
|
||||||
@ -185,7 +186,7 @@ export class CommandLineParser {
|
|||||||
}).parseSync();
|
}).parseSync();
|
||||||
|
|
||||||
const configPath = cliArguments.configPath ?? this.default.configPath;
|
const configPath = cliArguments.configPath ?? this.default.configPath;
|
||||||
setConfigFilePath(configPath);
|
initConfig(configPath);
|
||||||
/** @type {CommandLineArguments} */
|
/** @type {CommandLineArguments} */
|
||||||
const result = {
|
const result = {
|
||||||
configPath: configPath,
|
configPath: configPath,
|
||||||
|
197
src/config-init.js
Normal file
197
src/config-init.js
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
import yaml from 'yaml';
|
||||||
|
import color from 'chalk';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { serverDirectory } from './server-directory.js';
|
||||||
|
import { setConfigFilePath } from './util.js';
|
||||||
|
|
||||||
|
const keyMigrationMap = [
|
||||||
|
{
|
||||||
|
oldKey: 'disableThumbnails',
|
||||||
|
newKey: 'thumbnails.enabled',
|
||||||
|
migrate: (value) => !value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'thumbnailsQuality',
|
||||||
|
newKey: 'thumbnails.quality',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'avatarThumbnailsPng',
|
||||||
|
newKey: 'thumbnails.format',
|
||||||
|
migrate: (value) => (value ? 'png' : 'jpg'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'disableChatBackup',
|
||||||
|
newKey: 'backups.chat.enabled',
|
||||||
|
migrate: (value) => !value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'numberOfBackups',
|
||||||
|
newKey: 'backups.common.numberOfBackups',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'maxTotalChatBackups',
|
||||||
|
newKey: 'backups.chat.maxTotalBackups',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'chatBackupThrottleInterval',
|
||||||
|
newKey: 'backups.chat.throttleInterval',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'enableExtensions',
|
||||||
|
newKey: 'extensions.enabled',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'enableExtensionsAutoUpdate',
|
||||||
|
newKey: 'extensions.autoUpdate',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.disableAutoDownload',
|
||||||
|
newKey: 'extensions.models.autoDownload',
|
||||||
|
migrate: (value) => !value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.classificationModel',
|
||||||
|
newKey: 'extensions.models.classification',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.captioningModel',
|
||||||
|
newKey: 'extensions.models.captioning',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.embeddingModel',
|
||||||
|
newKey: 'extensions.models.embedding',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.speechToTextModel',
|
||||||
|
newKey: 'extensions.models.speechToText',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'extras.textToSpeechModel',
|
||||||
|
newKey: 'extensions.models.textToSpeech',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'minLogLevel',
|
||||||
|
newKey: 'logging.minLogLevel',
|
||||||
|
migrate: (value) => value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'cardsCacheCapacity',
|
||||||
|
newKey: 'performance.memoryCacheCapacity',
|
||||||
|
migrate: (value) => `${value}mb`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
oldKey: 'cookieSecret',
|
||||||
|
newKey: 'cookieSecret',
|
||||||
|
migrate: () => void 0,
|
||||||
|
remove: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) || obj === null) {
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the current config.yaml with the default config.yaml and adds any missing values.
|
||||||
|
* @param {string} configPath Path to config.yaml
|
||||||
|
*/
|
||||||
|
export function addMissingConfigValues(configPath) {
|
||||||
|
try {
|
||||||
|
const defaultConfig = yaml.parse(fs.readFileSync(path.join(serverDirectory, './default/config.yaml'), 'utf8'));
|
||||||
|
let config = yaml.parse(fs.readFileSync(configPath, 'utf8'));
|
||||||
|
|
||||||
|
// Migrate old keys to new keys
|
||||||
|
const migratedKeys = [];
|
||||||
|
for (const { oldKey, newKey, migrate, remove } of keyMigrationMap) {
|
||||||
|
if (_.has(config, oldKey)) {
|
||||||
|
if (remove) {
|
||||||
|
_.unset(config, oldKey);
|
||||||
|
migratedKeys.push({
|
||||||
|
oldKey,
|
||||||
|
newValue: void 0,
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldValue = _.get(config, oldKey);
|
||||||
|
const newValue = migrate(oldValue);
|
||||||
|
_.set(config, newKey, newValue);
|
||||||
|
_.unset(config, oldKey);
|
||||||
|
|
||||||
|
migratedKeys.push({
|
||||||
|
oldKey,
|
||||||
|
newKey,
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 && migratedKeys.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedKeys.length > 0) {
|
||||||
|
console.log('Adding missing config values to config.yaml:', addedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (migratedKeys.length > 0) {
|
||||||
|
console.log('Migrating config values in config.yaml:', migratedKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(configPath, yaml.stringify(config));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(color.red('FATAL: Could not add missing config values to config.yaml'), error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs early initialization tasks before the server starts.
|
||||||
|
* @param {string} configPath Path to config.yaml
|
||||||
|
*/
|
||||||
|
export function initConfig(configPath) {
|
||||||
|
setConfigFilePath(configPath);
|
||||||
|
addMissingConfigValues(configPath);
|
||||||
|
}
|
@ -12,7 +12,6 @@ configureTransformers();
|
|||||||
function configureTransformers() {
|
function configureTransformers() {
|
||||||
// Limit the number of threads to 1 to avoid issues on Android
|
// Limit the number of threads to 1 to avoid issues on Android
|
||||||
env.backends.onnx.wasm.numThreads = 1;
|
env.backends.onnx.wasm.numThreads = 1;
|
||||||
console.log(env.backends.onnx.wasm.wasmPaths);
|
|
||||||
// Use WASM from a local folder to avoid CDN connections
|
// Use WASM from a local folder to avoid CDN connections
|
||||||
env.backends.onnx.wasm.wasmPaths = path.join(serverDirectory, 'node_modules', 'sillytavern-transformers', 'dist') + path.sep;
|
env.backends.onnx.wasm.wasmPaths = path.join(serverDirectory, 'node_modules', 'sillytavern-transformers', 'dist') + path.sep;
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ import yauzl from 'yauzl';
|
|||||||
import mime from 'mime-types';
|
import mime from 'mime-types';
|
||||||
import { default as simpleGit } from 'simple-git';
|
import { default as simpleGit } from 'simple-git';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import { LOG_LEVELS } from './constants.js';
|
|
||||||
import bytes from 'bytes';
|
import bytes from 'bytes';
|
||||||
|
import { LOG_LEVELS } from './constants.js';
|
||||||
import { serverDirectory } from './server-directory.js';
|
import { serverDirectory } from './server-directory.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user