mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
re-implement sillytavern to be manually and locally installed instead of relying on npx, update systeminformation, less main layout padding
This commit is contained in:
parent
f9feb71926
commit
ef9d814dd2
4 changed files with 123 additions and 46 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "gerbil",
|
"name": "gerbil",
|
||||||
"productName": "Gerbil",
|
"productName": "Gerbil",
|
||||||
"version": "1.17.1",
|
"version": "1.18.0",
|
||||||
"description": "Run Large Language Models locally",
|
"description": "Run Large Language Models locally",
|
||||||
"main": "out/main/index.js",
|
"main": "out/main/index.js",
|
||||||
"homepage": "./",
|
"homepage": "./",
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/search": "^6.5.11",
|
"@codemirror/search": "^6.5.11",
|
||||||
"@codemirror/theme-one-dark": "^6.1.3",
|
"@codemirror/theme-one-dark": "^6.1.3",
|
||||||
"@codemirror/view": "^6.39.5",
|
"@codemirror/view": "^6.39.6",
|
||||||
"@fontsource/inter": "^5.2.8",
|
"@fontsource/inter": "^5.2.8",
|
||||||
"@huggingface/gguf": "^0.3.2",
|
"@huggingface/gguf": "^0.3.2",
|
||||||
"@mantine/core": "^8.3.10",
|
"@mantine/core": "^8.3.10",
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
"rehype-raw": "^7.0.0",
|
"rehype-raw": "^7.0.0",
|
||||||
"rehype-sanitize": "^6.0.0",
|
"rehype-sanitize": "^6.0.0",
|
||||||
"remark-gfm": "^4.0.1",
|
"remark-gfm": "^4.0.1",
|
||||||
"systeminformation": "^5.27.15",
|
"systeminformation": "^5.27.16",
|
||||||
"winston": "^3.19.0",
|
"winston": "^3.19.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0",
|
"winston-daily-rotate-file": "^5.0.0",
|
||||||
"yauzl": "^3.2.0",
|
"yauzl": "^3.2.0",
|
||||||
|
|
|
||||||
|
|
@ -252,8 +252,10 @@ export const App = () => {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
overflow: 'auto',
|
overflow: 'auto',
|
||||||
paddingTop: 0,
|
paddingTop: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
paddingLeft: isInterfaceScreen ? 0 : '.5rem',
|
||||||
|
paddingRight: isInterfaceScreen ? 0 : '.5rem',
|
||||||
top: TITLEBAR_HEIGHT,
|
top: TITLEBAR_HEIGHT,
|
||||||
paddingBottom: isInterfaceScreen ? 0 : '1rem',
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { createServer, request, type Server } from 'http';
|
import { createServer, request, type Server } from 'http';
|
||||||
import { homedir } from 'os';
|
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { platform, on } from 'process';
|
import { platform, on } from 'process';
|
||||||
import type { ChildProcess } from 'child_process';
|
import type { ChildProcess } from 'child_process';
|
||||||
|
|
@ -13,14 +12,12 @@ import { terminateProcess } from '@/utils/node/process';
|
||||||
import { pathExists, readJsonFile, writeJsonFile } from '@/utils/node/fs';
|
import { pathExists, readJsonFile, writeJsonFile } from '@/utils/node/fs';
|
||||||
import { parseKoboldConfig } from '@/utils/node/kobold';
|
import { parseKoboldConfig } from '@/utils/node/kobold';
|
||||||
import { getNodeEnvironment } from './dependencies';
|
import { getNodeEnvironment } from './dependencies';
|
||||||
|
import { getInstallDir } from './config';
|
||||||
|
|
||||||
let sillyTavernProcess: ChildProcess | null = null;
|
let sillyTavernProcess: ChildProcess | null = null;
|
||||||
let proxyServer: Server | null = null;
|
let proxyServer: Server | null = null;
|
||||||
let detectedDataRoot: string | null = null;
|
|
||||||
|
|
||||||
const SILLYTAVERN_BASE_ARGS = [
|
const SILLYTAVERN_BASE_ARGS = [
|
||||||
'sillytavern',
|
|
||||||
'--global',
|
|
||||||
'--listen',
|
'--listen',
|
||||||
'--browserLaunchEnabled',
|
'--browserLaunchEnabled',
|
||||||
'false',
|
'false',
|
||||||
|
|
@ -35,47 +32,120 @@ on('SIGTERM', () => {
|
||||||
void stopFrontend();
|
void stopFrontend();
|
||||||
});
|
});
|
||||||
|
|
||||||
function getFallbackDataRoot() {
|
function getSillyTavernDataDir() {
|
||||||
const home = homedir();
|
return join(getInstallDir(), 'sillytavern-data');
|
||||||
|
}
|
||||||
|
|
||||||
switch (platform) {
|
function getSillyTavernInstallDir() {
|
||||||
case 'win32':
|
return join(getInstallDir(), 'sillytavern-server');
|
||||||
return join(home, 'AppData', 'Local', 'SillyTavern', 'Data', 'data');
|
}
|
||||||
case 'darwin':
|
|
||||||
|
function getSillyTavernServerPath() {
|
||||||
return join(
|
return join(
|
||||||
home,
|
getSillyTavernInstallDir(),
|
||||||
'Library',
|
'node_modules',
|
||||||
'Application Support',
|
'sillytavern',
|
||||||
'SillyTavern',
|
'server.js'
|
||||||
'data'
|
|
||||||
);
|
);
|
||||||
case 'linux':
|
|
||||||
default:
|
|
||||||
return join(home, '.local', 'share', 'SillyTavern', 'data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSillyTavernDataRoot() {
|
|
||||||
if (detectedDataRoot) {
|
|
||||||
return detectedDataRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fallback = getFallbackDataRoot();
|
|
||||||
detectedDataRoot = fallback;
|
|
||||||
return fallback;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSillyTavernSettingsPath() {
|
function getSillyTavernSettingsPath() {
|
||||||
const dataRoot = getSillyTavernDataRoot();
|
return join(getSillyTavernDataDir(), 'default-user', 'settings.json');
|
||||||
return join(dataRoot, 'default-user', 'settings.json');
|
}
|
||||||
|
|
||||||
|
async function ensureSillyTavernInstalled() {
|
||||||
|
const serverPath = getSillyTavernServerPath();
|
||||||
|
const installDir = getSillyTavernInstallDir();
|
||||||
|
const env = await getNodeEnvironment();
|
||||||
|
|
||||||
|
const nodeModulesPath = join(installDir, 'node_modules');
|
||||||
|
const jsquashFlatPath = join(nodeModulesPath, '@jsquash');
|
||||||
|
|
||||||
|
if (await pathExists(jsquashFlatPath)) {
|
||||||
|
sendKoboldOutput('Detected old flat installation, cleaning up...');
|
||||||
|
await tryExecute(async () => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const rmCmd = platform === 'win32' ? 'rmdir' : 'rm';
|
||||||
|
const rmArgs =
|
||||||
|
platform === 'win32'
|
||||||
|
? ['/s', '/q', nodeModulesPath]
|
||||||
|
: ['-rf', nodeModulesPath];
|
||||||
|
|
||||||
|
spawn(rmCmd, rmArgs, {
|
||||||
|
stdio: 'inherit',
|
||||||
|
shell: true,
|
||||||
|
})
|
||||||
|
.on('exit', (code) =>
|
||||||
|
code === 0
|
||||||
|
? resolve()
|
||||||
|
: reject(new Error(`Failed with code ${code}`))
|
||||||
|
)
|
||||||
|
.on('error', reject);
|
||||||
|
});
|
||||||
|
}, 'Failed to clean old installation');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await pathExists(serverPath)) {
|
||||||
|
sendKoboldOutput('Checking for SillyTavern updates...');
|
||||||
|
} else {
|
||||||
|
sendKoboldOutput('Installing SillyTavern via npm...');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
const npmProcess = spawn(
|
||||||
|
'npm',
|
||||||
|
[
|
||||||
|
'install',
|
||||||
|
'sillytavern@latest',
|
||||||
|
'--prefix',
|
||||||
|
installDir,
|
||||||
|
'--no-save',
|
||||||
|
'--install-strategy=nested',
|
||||||
|
],
|
||||||
|
{
|
||||||
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
|
env,
|
||||||
|
shell: platform === 'win32',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (npmProcess.stdout) {
|
||||||
|
npmProcess.stdout.on('data', (data: Buffer) => {
|
||||||
|
sendKoboldOutput(data.toString().trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (npmProcess.stderr) {
|
||||||
|
npmProcess.stderr.on('data', (data: Buffer) => {
|
||||||
|
sendKoboldOutput(data.toString().trim());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
npmProcess.on('exit', (code) => {
|
||||||
|
if (code === 0) {
|
||||||
|
sendKoboldOutput('SillyTavern is ready');
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject(new Error(`npm install failed with code ${code}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
npmProcess.on('error', (error) => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNpxProcess(args: string[]) {
|
async function createNpxProcess(args: string[]) {
|
||||||
const env = await getNodeEnvironment();
|
const env = await getNodeEnvironment();
|
||||||
return spawn('npx', args, {
|
const serverJsPath = getSillyTavernServerPath();
|
||||||
|
const installDir = getSillyTavernInstallDir();
|
||||||
|
|
||||||
|
return spawn('node', [serverJsPath, ...args], {
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
detached: false,
|
detached: false,
|
||||||
env,
|
env,
|
||||||
|
cwd: installDir,
|
||||||
shell: platform === 'win32',
|
shell: platform === 'win32',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -288,6 +358,7 @@ export async function startFrontend(args: string[]) {
|
||||||
|
|
||||||
sendKoboldOutput(`Preparing SillyTavern to connect via proxy...`);
|
sendKoboldOutput(`Preparing SillyTavern to connect via proxy...`);
|
||||||
|
|
||||||
|
await ensureSillyTavernInstalled();
|
||||||
await ensureSillyTavernSettings();
|
await ensureSillyTavernSettings();
|
||||||
await setupSillyTavernConfig(isImageMode);
|
await setupSillyTavernConfig(isImageMode);
|
||||||
|
|
||||||
|
|
@ -295,10 +366,14 @@ export async function startFrontend(args: string[]) {
|
||||||
`Starting ${config.name} frontend on port ${config.port}...`
|
`Starting ${config.name} frontend on port ${config.port}...`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const sillyTavernDataDir = getSillyTavernDataDir();
|
||||||
|
|
||||||
const sillyTavernArgs = [
|
const sillyTavernArgs = [
|
||||||
...SILLYTAVERN_BASE_ARGS,
|
...SILLYTAVERN_BASE_ARGS,
|
||||||
'--port',
|
'--port',
|
||||||
config.port.toString(),
|
config.port.toString(),
|
||||||
|
'--dataRoot',
|
||||||
|
sillyTavernDataDir,
|
||||||
];
|
];
|
||||||
|
|
||||||
sillyTavernProcess = await createNpxProcess(sillyTavernArgs);
|
sillyTavernProcess = await createNpxProcess(sillyTavernArgs);
|
||||||
|
|
|
||||||
20
yarn.lock
20
yarn.lock
|
|
@ -315,15 +315,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0, @codemirror/view@npm:^6.39.5":
|
"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0, @codemirror/view@npm:^6.39.6":
|
||||||
version: 6.39.5
|
version: 6.39.6
|
||||||
resolution: "@codemirror/view@npm:6.39.5"
|
resolution: "@codemirror/view@npm:6.39.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/state": "npm:^6.5.0"
|
"@codemirror/state": "npm:^6.5.0"
|
||||||
crelt: "npm:^1.0.6"
|
crelt: "npm:^1.0.6"
|
||||||
style-mod: "npm:^4.1.0"
|
style-mod: "npm:^4.1.0"
|
||||||
w3c-keyname: "npm:^2.2.4"
|
w3c-keyname: "npm:^2.2.4"
|
||||||
checksum: 10c0/54fc600b54c336283e8c73b6a0a99156880682121d73c2d4b74fc5a93f956e33b54ba16cd7debbf5fc28a48b18aeb643217e5200e3af0588909ca90cb275e957
|
checksum: 10c0/2c858a22c871f1865e09a4eb50b2398fc2ac945d217645c79692904bd0b48688ca2ba186fdfd5ed07fce671e22ae4424935efabcbc4d947c9559f801a4e94053
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
@ -4124,7 +4124,7 @@ __metadata:
|
||||||
dependencies:
|
dependencies:
|
||||||
"@codemirror/search": "npm:^6.5.11"
|
"@codemirror/search": "npm:^6.5.11"
|
||||||
"@codemirror/theme-one-dark": "npm:^6.1.3"
|
"@codemirror/theme-one-dark": "npm:^6.1.3"
|
||||||
"@codemirror/view": "npm:^6.39.5"
|
"@codemirror/view": "npm:^6.39.6"
|
||||||
"@eslint/js": "npm:^9.39.2"
|
"@eslint/js": "npm:^9.39.2"
|
||||||
"@fontsource/inter": "npm:^5.2.8"
|
"@fontsource/inter": "npm:^5.2.8"
|
||||||
"@huggingface/gguf": "npm:^0.3.2"
|
"@huggingface/gguf": "npm:^0.3.2"
|
||||||
|
|
@ -4165,7 +4165,7 @@ __metadata:
|
||||||
rehype-sanitize: "npm:^6.0.0"
|
rehype-sanitize: "npm:^6.0.0"
|
||||||
remark-gfm: "npm:^4.0.1"
|
remark-gfm: "npm:^4.0.1"
|
||||||
rollup-plugin-visualizer: "npm:^6.0.5"
|
rollup-plugin-visualizer: "npm:^6.0.5"
|
||||||
systeminformation: "npm:^5.27.15"
|
systeminformation: "npm:^5.27.16"
|
||||||
typescript: "npm:^5.9.3"
|
typescript: "npm:^5.9.3"
|
||||||
vite: "npm:^7.3.0"
|
vite: "npm:^7.3.0"
|
||||||
winston: "npm:^3.19.0"
|
winston: "npm:^3.19.0"
|
||||||
|
|
@ -7840,12 +7840,12 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"systeminformation@npm:^5.27.15":
|
"systeminformation@npm:^5.27.16":
|
||||||
version: 5.27.15
|
version: 5.27.16
|
||||||
resolution: "systeminformation@npm:5.27.15"
|
resolution: "systeminformation@npm:5.27.16"
|
||||||
bin:
|
bin:
|
||||||
systeminformation: lib/cli.js
|
systeminformation: lib/cli.js
|
||||||
checksum: 10c0/839d629eb9200ed9bc726a73d8b3a8cce0d77bd7796a983944099bd7a3ee48b93b27397a94eab3a5cc04a5fe61e46dcf3732691d33d70bdd0c638afca984990a
|
checksum: 10c0/2fc5fe3d081aeafff02ab89fa516df47559f15d017790f018208f75926e402df7f6e383c1a1716429093558545d4c8d57dd8fc2cf9aa568c4edc2f8e2dd0423f
|
||||||
conditions: (os=darwin | os=linux | os=win32 | os=freebsd | os=openbsd | os=netbsd | os=sunos | os=android)
|
conditions: (os=darwin | os=linux | os=win32 | os=freebsd | os=openbsd | os=netbsd | os=sunos | os=android)
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue