mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
prettify binary names, minor changes and improvements
This commit is contained in:
parent
1499445762
commit
d7e09f2ea5
23 changed files with 112 additions and 113 deletions
10
README.md
10
README.md
|
|
@ -8,7 +8,7 @@ A desktop app to easily run Large Language Models locally.
|
|||
|
||||
## Core Features
|
||||
|
||||
- **Run LLMs locally** powered by [KoboldCpp](https://github.com/LostRuins/koboldcpp) which itself is a highly modified fork of [llama.cpp](https://github.com/ggml-org/llama.cpp)
|
||||
- **Run LLMs locally** powered by a highly modified fork of [llama.cpp](https://github.com/ggml-org/llama.cpp)
|
||||
- **Cross-platform desktop app** - Native support for Windows, macOS, and Linux (including Wayland)
|
||||
- **Automatic updates** - Download and keep your KoboldCpp binary up-to-date effortlessly
|
||||
- **Smart process management** - Prevents runaway background processes and system resource waste
|
||||
|
|
@ -150,8 +150,12 @@ You can use the CLI mode on Windows in exactly the same way as in the Linux/macO
|
|||
yarn dev
|
||||
```
|
||||
|
||||
## Future Considerations
|
||||
|
||||
- migrate the project to Tauri from Electron?
|
||||
- transition to using llama.cpp binaries directly instead of running them indirectly through koboldcpp?
|
||||
- seamless support for more frontends?
|
||||
|
||||
## License
|
||||
|
||||
AGPL v3 License - see LICENSE file for details
|
||||
|
||||
# test
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gerbil",
|
||||
"productName": "Gerbil",
|
||||
"version": "0.9.9",
|
||||
"version": "1.0.0",
|
||||
"description": "Run Large Language Models locally",
|
||||
"main": "out/main/index.js",
|
||||
"homepage": "./",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { Checkbox, Group } from '@mantine/core';
|
||||
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
|
||||
interface CheckboxWithTooltipProps {
|
||||
checked: boolean;
|
||||
|
|
@ -17,7 +16,7 @@ export const CheckboxWithTooltip = ({
|
|||
tooltip,
|
||||
disabled = false,
|
||||
}: CheckboxWithTooltipProps) => (
|
||||
<div className={styles.minWidth200}>
|
||||
<div style={{ minWidth: '12.5rem' }}>
|
||||
<Group gap="xs" align="center">
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ const COMMAND_LINE_ARGUMENTS: ArgumentInfo[] = [
|
|||
{
|
||||
flag: '--cli',
|
||||
description:
|
||||
'Does not launch KoboldCpp HTTP server. Instead, enables KoboldCpp from the command line, accepting interactive console input and displaying responses to the terminal.',
|
||||
'Does not launch the HTTP server. Instead, enables input from the command line, accepting interactive console input and displaying responses to the terminal.',
|
||||
type: 'boolean',
|
||||
category: 'Advanced',
|
||||
},
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from '@mantine/core';
|
||||
import { Download } from 'lucide-react';
|
||||
import { MouseEvent } from 'react';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
import { pretifyBinName } from '@/utils/assets';
|
||||
|
||||
interface DownloadCardProps {
|
||||
name: string;
|
||||
|
|
@ -126,10 +126,10 @@ export const DownloadCard = ({
|
|||
})}
|
||||
>
|
||||
<Group justify="space-between" align="center">
|
||||
<div className={styles.flex1}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Group gap="xs" align="center" mb="xs">
|
||||
<Text fw={500} size="sm">
|
||||
{name}
|
||||
{pretifyBinName(name)}
|
||||
</Text>
|
||||
{isCurrent && (
|
||||
<Badge variant="light" color="blue" size="sm">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Group, TextInput, Button } from '@mantine/core';
|
|||
import { File, Search } from 'lucide-react';
|
||||
import { LabelWithTooltip } from '@/components/LabelWithTooltip';
|
||||
import { getInputValidationState } from '@/utils/validation';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
|
||||
interface ModelFileFieldProps {
|
||||
label: string;
|
||||
|
|
@ -41,7 +40,7 @@ export const ModelFileField = ({
|
|||
<div>
|
||||
<LabelWithTooltip label={label} tooltip={tooltip} />
|
||||
<Group gap="xs" align="flex-start">
|
||||
<div className={styles.flex1}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<TextInput
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const ServerTab = ({
|
|||
>
|
||||
<Stack align="center" gap="md" mt="xl">
|
||||
<Text c="dimmed" size="lg">
|
||||
Waiting for the KoboldCpp server to start...
|
||||
Waiting for the server to start...
|
||||
</Text>
|
||||
<Text c="dimmed" size="sm">
|
||||
The {isImageGenerationMode ? 'image generation' : 'chat'} interface
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import {
|
|||
useComputedColorScheme,
|
||||
} from '@mantine/core';
|
||||
import { ChevronDown } from 'lucide-react';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
import { SERVER_READY_SIGNALS, TITLEBAR_HEIGHT } from '@/constants';
|
||||
import { handleTerminalOutput, processTerminalContent } from '@/utils/terminal';
|
||||
import { useLaunchConfigStore } from '@/stores/launchConfig';
|
||||
|
|
@ -120,14 +119,19 @@ export const TerminalTab = ({
|
|||
ref={scrollAreaRef}
|
||||
viewportRef={viewportRef}
|
||||
onScrollPositionChange={handleScroll}
|
||||
className={styles.terminalScrollArea}
|
||||
style={{
|
||||
flex: 1,
|
||||
fontFamily: 'Monaco, Menlo, Ubuntu Mono, monospace',
|
||||
fontSize: '0.875em',
|
||||
lineHeight: 1.4,
|
||||
}}
|
||||
scrollbarSize={8}
|
||||
offsetScrollbars={false}
|
||||
>
|
||||
<Box p="md">
|
||||
{terminalContent.length === 0 ? (
|
||||
<Text c="dimmed" style={{ fontFamily: 'inherit' }}>
|
||||
Starting KoboldCpp...
|
||||
Starting...
|
||||
</Text>
|
||||
) : (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ export const AdvancedTab = () => {
|
|||
<Text size="sm" fw={500}>
|
||||
Additional arguments
|
||||
</Text>
|
||||
<InfoTooltip label="Additional command line arguments to pass to the KoboldCPP binary. Leave this empty if you don't know what they are." />
|
||||
<InfoTooltip label="Additional command line arguments to pass to the binary. Leave this empty if you don't know what they are." />
|
||||
</Group>
|
||||
<Button
|
||||
size="xs"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Stack, Text, Group, Button, Select } from '@mantine/core';
|
|||
import { useState, useCallback } from 'react';
|
||||
import { Save, File, Plus, Check } from 'lucide-react';
|
||||
import type { ConfigFile } from '@/types';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
import { CreateConfigModal } from './CreateConfigModal';
|
||||
|
||||
interface ConfigFileManagerProps {
|
||||
|
|
@ -67,7 +66,7 @@ export const ConfigFileManager = ({
|
|||
Configuration
|
||||
</Text>
|
||||
<Group gap="xs" align="flex-end">
|
||||
<div className={styles.flex1}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<Select
|
||||
placeholder="Select a configuration file"
|
||||
value={selectedFile}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export const NetworkTab = () => {
|
|||
<Text size="sm" fw={500}>
|
||||
Host
|
||||
</Text>
|
||||
<InfoTooltip label="The hostname or IP address on which KoboldCpp will bind its webserver to." />
|
||||
<InfoTooltip label="The hostname or IP address to bind the webserver to." />
|
||||
</Group>
|
||||
<TextInput
|
||||
placeholder="localhost"
|
||||
|
|
@ -49,7 +49,7 @@ export const NetworkTab = () => {
|
|||
<Text size="sm" fw={500}>
|
||||
Port
|
||||
</Text>
|
||||
<InfoTooltip label="The port number on which KoboldCpp will listen for connections. Leave empty to use default port 5001." />
|
||||
<InfoTooltip label="The port number on which the server will listen for connections. Leave empty to use default port 5001." />
|
||||
</Group>
|
||||
<TextInput
|
||||
placeholder="5001"
|
||||
|
|
@ -105,7 +105,7 @@ export const NetworkTab = () => {
|
|||
checked={remotetunnel}
|
||||
onChange={handleRemotetunnelChange}
|
||||
label="Remote Tunnel"
|
||||
tooltip="Creates a trycloudflare tunnel. Allows you to access koboldcpp from other devices over an internet URL."
|
||||
tooltip="Creates a trycloudflare tunnel. Allows you to access your server from other devices over an internet URL."
|
||||
/>
|
||||
|
||||
<CheckboxWithTooltip
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@ import {
|
|||
Group,
|
||||
List,
|
||||
ThemeIcon,
|
||||
Anchor,
|
||||
Image,
|
||||
} from '@mantine/core';
|
||||
import { Check, ExternalLink } from 'lucide-react';
|
||||
import { Check } from 'lucide-react';
|
||||
import iconUrl from '/icon.png';
|
||||
|
||||
interface WelcomeScreenProps {
|
||||
onGetStarted: () => void;
|
||||
|
|
@ -23,9 +24,12 @@ export const WelcomeScreen = ({ onGetStarted }: WelcomeScreenProps) => (
|
|||
<Card withBorder radius="md" shadow="sm" p="xl">
|
||||
<Stack gap="lg" align="center">
|
||||
<Stack gap="md" align="center">
|
||||
<Title order={1} ta="center">
|
||||
{PRODUCT_NAME}
|
||||
</Title>
|
||||
<Group gap="md" mr="xl" align="center">
|
||||
<Image src={iconUrl} alt={PRODUCT_NAME} w={36} h={36} />
|
||||
<Title order={1} ta="center">
|
||||
{PRODUCT_NAME}
|
||||
</Title>
|
||||
</Group>
|
||||
<Text size="lg" c="dimmed" ta="center" maw={600}>
|
||||
Run Large Language Models locally
|
||||
</Text>
|
||||
|
|
@ -84,44 +88,9 @@ export const WelcomeScreen = ({ onGetStarted }: WelcomeScreenProps) => (
|
|||
</Text>
|
||||
</Stack>
|
||||
|
||||
<Button size="lg" onClick={onGetStarted}>
|
||||
<Button size="lg" mt="lg" onClick={onGetStarted}>
|
||||
Get Started
|
||||
</Button>
|
||||
|
||||
<Group gap="lg" mt="md">
|
||||
<Anchor
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
window.electronAPI.app.openExternal(
|
||||
'https://github.com/LostRuins/koboldcpp'
|
||||
);
|
||||
}}
|
||||
size="sm"
|
||||
c="dimmed"
|
||||
>
|
||||
<Group gap={4} align="center">
|
||||
<span>About KoboldCpp</span>
|
||||
<ExternalLink size={12} />
|
||||
</Group>
|
||||
</Anchor>
|
||||
<Anchor
|
||||
href="#"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
window.electronAPI.app.openExternal(
|
||||
'https://github.com/lone-cloud/gerbil'
|
||||
);
|
||||
}}
|
||||
size="sm"
|
||||
c="dimmed"
|
||||
>
|
||||
<Group gap={4} align="center">
|
||||
<span>About Gerbil</span>
|
||||
<ExternalLink size={12} />
|
||||
</Group>
|
||||
</Anchor>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Card>
|
||||
</Stack>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@ import {
|
|||
Badge,
|
||||
Button,
|
||||
rem,
|
||||
ActionIcon,
|
||||
Tooltip,
|
||||
} from '@mantine/core';
|
||||
import { Github, FolderOpen } from 'lucide-react';
|
||||
import { Github, FolderOpen, Copy } from 'lucide-react';
|
||||
import { safeExecute } from '@/utils/logger';
|
||||
import type { VersionInfo } from '@/types/electron';
|
||||
import { PRODUCT_NAME } from '@/constants';
|
||||
|
|
@ -50,6 +52,22 @@ export const AboutTab = () => {
|
|||
},
|
||||
];
|
||||
|
||||
const copyVersionInfo = async () => {
|
||||
const info = [
|
||||
`${PRODUCT_NAME} v${versionInfo.appVersion}`,
|
||||
`Electron: ${versionInfo.electronVersion}`,
|
||||
`Node.js: ${versionInfo.nodeVersion}`,
|
||||
`Chromium: ${versionInfo.chromeVersion}`,
|
||||
`V8: ${versionInfo.v8Version}`,
|
||||
`OS: ${versionInfo.platform} ${versionInfo.arch} (${versionInfo.osVersion})`,
|
||||
].join('\n');
|
||||
|
||||
await safeExecute(
|
||||
() => navigator.clipboard.writeText(info),
|
||||
'Failed to copy version info'
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Stack gap="md">
|
||||
<Card withBorder radius="md" p="xs">
|
||||
|
|
@ -118,7 +136,23 @@ export const AboutTab = () => {
|
|||
</Group>
|
||||
</Card>
|
||||
|
||||
<Card withBorder radius="md" p="xs">
|
||||
<Card withBorder radius="md" p="xs" style={{ position: 'relative' }}>
|
||||
<Tooltip label="Copy info">
|
||||
<ActionIcon
|
||||
variant="subtle"
|
||||
size="sm"
|
||||
onClick={copyVersionInfo}
|
||||
aria-label="Copy Info"
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 8,
|
||||
right: 8,
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
<Copy style={{ width: rem(14), height: rem(14) }} />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
<Stack gap="xs">
|
||||
{versionItems.map((item, index) => (
|
||||
<Group key={index} gap="md" align="center" wrap="nowrap">
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import {
|
|||
Anchor,
|
||||
} from '@mantine/core';
|
||||
import { Folder, FolderOpen, Monitor } from 'lucide-react';
|
||||
import styles from '@/styles/layout.module.css';
|
||||
import type { FrontendPreference } from '@/types';
|
||||
import { FRONTENDS } from '@/constants';
|
||||
|
||||
|
|
@ -39,7 +38,7 @@ export const GeneralTab = () => {
|
|||
|
||||
const frontendConfigs: FrontendConfig[] = useMemo(
|
||||
() => [
|
||||
{ value: 'koboldcpp', label: 'KoboldCpp (Built-in)' },
|
||||
{ value: 'koboldcpp', label: 'Built-in Interface' },
|
||||
{
|
||||
value: 'sillytavern',
|
||||
label: FRONTENDS.SILLYTAVERN,
|
||||
|
|
@ -195,7 +194,7 @@ export const GeneralTab = () => {
|
|||
value={installDir}
|
||||
readOnly
|
||||
placeholder="Default installation directory"
|
||||
className={styles.flex1}
|
||||
style={{ flex: 1 }}
|
||||
leftSection={<Folder style={{ width: rem(16), height: rem(16) }} />}
|
||||
/>
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ export const useLaunchLogic = ({
|
|||
);
|
||||
}
|
||||
} catch (err) {
|
||||
error('Error launching KoboldCpp:', err as Error);
|
||||
error('Error launching:', err as Error);
|
||||
} finally {
|
||||
setIsLaunching(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ const checkGpuWarnings = async (
|
|||
warnings.push({
|
||||
type: 'warning',
|
||||
message:
|
||||
'Your KoboldCpp binary supports CUDA and you have an NVIDIA GPU, but CUDA runtime is not detected on your system.',
|
||||
'Your binary supports CUDA and you have an NVIDIA GPU, but CUDA runtime is not detected on your system.',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ const checkGpuWarnings = async (
|
|||
warnings.push({
|
||||
type: 'warning',
|
||||
message:
|
||||
'Your KoboldCpp binary supports ROCm and you have an AMD GPU, but ROCm runtime is not detected on your system.',
|
||||
'Your binary supports ROCm and you have an AMD GPU, but ROCm runtime is not detected on your system.',
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ export class LightweightCliHandler {
|
|||
|
||||
if (!currentBinary) {
|
||||
console.error(
|
||||
'Error: No KoboldCpp binary found. Please run the GUI first to download KoboldCpp.'
|
||||
'Error: No binary found. Please run the GUI first to download the binary.'
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!(await pathExists(currentBinary))) {
|
||||
console.error(`Error: KoboldCpp binary not found at: ${currentBinary}`);
|
||||
console.error('Please run the GUI to download or reconfigure KoboldCpp.');
|
||||
console.error(`Error: Binary not found at: ${currentBinary}`);
|
||||
console.error('Please run the GUI to download and configure the binary.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -75,12 +75,12 @@ export class LightweightCliHandler {
|
|||
});
|
||||
|
||||
child.on('error', (error) => {
|
||||
console.error(`Failed to start KoboldCpp: ${error.message}`);
|
||||
console.error(`Failed to start: ${error.message}`);
|
||||
reject(error);
|
||||
});
|
||||
|
||||
const handleSignal = async () => {
|
||||
console.log('\nReceived termination signal, terminating KoboldCpp...');
|
||||
console.log('\nReceived termination signal, terminating...');
|
||||
if (!child.killed) {
|
||||
await terminateProcess(child, {
|
||||
timeoutMs: 5000,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export class KoboldCppManager {
|
|||
try {
|
||||
if (this.koboldProcess && !this.koboldProcess.killed) {
|
||||
this.windowManager.sendKoboldOutput(
|
||||
'Stopping KoboldCpp process before update...'
|
||||
'Stopping process before update...'
|
||||
);
|
||||
await this.cleanup();
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
|
@ -91,7 +91,7 @@ export class KoboldCppManager {
|
|||
);
|
||||
throw new Error(
|
||||
`Cannot update: Failed to remove existing installation. ` +
|
||||
`Please ensure KoboldCpp is stopped and try again. ` +
|
||||
`Please ensure the server is stopped and try again. ` +
|
||||
`Error: ${(error as Error).message}`
|
||||
);
|
||||
}
|
||||
|
|
@ -182,7 +182,7 @@ export class KoboldCppManager {
|
|||
}
|
||||
|
||||
if (!launcherPath || !(await pathExists(launcherPath))) {
|
||||
throw new Error('Failed to find or create koboldcpp launcher');
|
||||
throw new Error('Failed to find or create launcher');
|
||||
}
|
||||
|
||||
return launcherPath;
|
||||
|
|
@ -633,8 +633,8 @@ export class KoboldCppManager {
|
|||
if (!currentVersion || !(await pathExists(currentVersion.path))) {
|
||||
const rawPath = this.configManager.getCurrentKoboldBinary();
|
||||
const error = currentVersion
|
||||
? `KoboldCpp binary file does not exist at path: ${currentVersion.path}`
|
||||
: 'No KoboldCpp version configured';
|
||||
? `Binary file does not exist at path: ${currentVersion.path}`
|
||||
: 'No version configured';
|
||||
|
||||
this.logManager.logError(
|
||||
`Launch failed: ${error}. Raw config path: "${rawPath}", Current version: ${JSON.stringify(currentVersion)}`
|
||||
|
|
@ -717,10 +717,7 @@ export class KoboldCppManager {
|
|||
});
|
||||
|
||||
child.on('error', (error) => {
|
||||
this.logManager.logError(
|
||||
`KoboldCpp process error: ${error.message}`,
|
||||
error
|
||||
);
|
||||
this.logManager.logError(`Process error: ${error.message}`, error);
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`\n[ERROR] Process error: ${error.message}\n`
|
||||
|
|
@ -736,7 +733,7 @@ export class KoboldCppManager {
|
|||
} catch (error) {
|
||||
const errorMessage = (error as Error).message;
|
||||
this.logManager.logError(
|
||||
`Failed to launch KoboldCpp: ${errorMessage}`,
|
||||
`Failed to launch: ${errorMessage}`,
|
||||
error as Error
|
||||
);
|
||||
return { success: false, error: errorMessage };
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import { app } from 'electron';
|
||||
import { join } from 'path';
|
||||
import winston from 'winston';
|
||||
import 'winston-daily-rotate-file';
|
||||
import { createLogger, format, type Logger } from 'winston';
|
||||
import DailyRotateFile from 'winston-daily-rotate-file';
|
||||
|
||||
export class LogManager {
|
||||
private logger: winston.Logger;
|
||||
private logger: Logger;
|
||||
|
||||
constructor() {
|
||||
const logsDir = join(app.getPath('userData'), 'logs');
|
||||
|
||||
this.logger = winston.createLogger({
|
||||
this.logger = createLogger({
|
||||
level: process.env.NODE_ENV === 'development' ? 'debug' : 'info',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.printf(({ timestamp, level, message, error }) => {
|
||||
format: format.combine(
|
||||
format.timestamp(),
|
||||
format.printf(({ timestamp, level, message, error }) => {
|
||||
const processInfo = `[${process.type || 'unknown'}:${process.pid}]`;
|
||||
let logEntry = `${timestamp} ${processInfo} [${level.toUpperCase()}] ${message}`;
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ export class LogManager {
|
|||
})
|
||||
),
|
||||
transports: [
|
||||
new winston.transports.DailyRotateFile({
|
||||
new DailyRotateFile({
|
||||
filename: join(logsDir, 'gerbil-%DATE%.log'),
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
maxSize: '10m',
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ export class OpenWebUIManager {
|
|||
await this.stopFrontend();
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`Preparing Open WebUI to connect to KoboldCpp at ${koboldHost}:${koboldPort}...`
|
||||
`Preparing Open WebUI to connect at ${koboldHost}:${koboldPort}...`
|
||||
);
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
|
|
@ -252,13 +252,13 @@ export class OpenWebUIManager {
|
|||
await this.waitForOpenWebUIToStart();
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`Open WebUI is ready and auto-configured for KoboldCpp!`
|
||||
`Open WebUI is ready and auto-configured!`
|
||||
);
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`Access Open WebUI at: http://localhost:${config.port}`
|
||||
);
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`KoboldCpp connection: ${koboldUrl}/v1 (auto-configured)`
|
||||
`Connection: ${koboldUrl}/v1 (auto-configured)`
|
||||
);
|
||||
} catch (error) {
|
||||
this.logManager.logError(
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ export class SillyTavernManager {
|
|||
textgenSettings.type = 'koboldcpp';
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`Configured SillyTavern for text generation with KoboldCpp at ${koboldUrl}`
|
||||
`Configured SillyTavern for text generation at ${koboldUrl}`
|
||||
);
|
||||
|
||||
await writeJsonFile(configPath, settings);
|
||||
|
|
@ -461,7 +461,7 @@ export class SillyTavernManager {
|
|||
await this.stopFrontend();
|
||||
|
||||
this.windowManager.sendKoboldOutput(
|
||||
`Preparing SillyTavern to connect to KoboldCpp at ${koboldHost}:${koboldPort}...`
|
||||
`Preparing SillyTavern to connect at ${koboldHost}:${koboldPort}...`
|
||||
);
|
||||
|
||||
await this.ensureSillyTavernSettings();
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
.minWidth200 {
|
||||
min-width: 12.5rem;
|
||||
}
|
||||
|
||||
.flex1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.terminalScrollArea {
|
||||
flex: 1;
|
||||
font-family: Monaco, Menlo, 'Ubuntu Mono', monospace;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
|
@ -53,3 +53,12 @@ export const sortDownloadsByType = <T extends { name: string }>(
|
|||
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
|
||||
export const pretifyBinName = (binName: string) =>
|
||||
binName
|
||||
.replace('koboldcpp-', '')
|
||||
.replace('-x64', ' (x64) ')
|
||||
.replace(' -', ' ')
|
||||
.replace('rocm', '- ROCm')
|
||||
.replace('nocuda', '- NoCUDA')
|
||||
.replace('oldpc', '- OldPC');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue