mirror of
https://github.com/lone-cloud/gerbil
synced 2026-06-03 19:54:44 -07:00
Adding new "Pre-Launch Commands" to the "Advanced" launch tab to allow launching commands before the launch
This commit is contained in:
parent
7a118c9449
commit
6100a4d0f0
15 changed files with 245 additions and 80 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "gerbil",
|
"name": "gerbil",
|
||||||
"productName": "Gerbil",
|
"productName": "Gerbil",
|
||||||
"version": "1.12.1",
|
"version": "1.13.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": "./",
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ import {
|
||||||
NumberInput,
|
NumberInput,
|
||||||
Button,
|
Button,
|
||||||
SimpleGrid,
|
SimpleGrid,
|
||||||
|
ActionIcon,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
|
import { Plus, Trash2 } from 'lucide-react';
|
||||||
import { InfoTooltip } from '@/components/InfoTooltip';
|
import { InfoTooltip } from '@/components/InfoTooltip';
|
||||||
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
import { CheckboxWithTooltip } from '@/components/CheckboxWithTooltip';
|
||||||
import { CommandLineArgumentsModal } from '@/components/screens/Launch/CommandLineArgumentsModal';
|
import { CommandLineArgumentsModal } from '@/components/screens/Launch/CommandLineArgumentsModal';
|
||||||
|
|
@ -16,6 +18,7 @@ import { useLaunchConfig } from '@/hooks/useLaunchConfig';
|
||||||
export const AdvancedTab = () => {
|
export const AdvancedTab = () => {
|
||||||
const {
|
const {
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
|
preLaunchCommands,
|
||||||
noshift,
|
noshift,
|
||||||
flashattention,
|
flashattention,
|
||||||
noavx2,
|
noavx2,
|
||||||
|
|
@ -28,6 +31,7 @@ export const AdvancedTab = () => {
|
||||||
moecpu,
|
moecpu,
|
||||||
moeexperts,
|
moeexperts,
|
||||||
handleAdditionalArgumentsChange,
|
handleAdditionalArgumentsChange,
|
||||||
|
handlePreLaunchCommandsChange,
|
||||||
handleNoshiftChange,
|
handleNoshiftChange,
|
||||||
handleFlashattentionChange,
|
handleFlashattentionChange,
|
||||||
handleNoavx2Change,
|
handleNoavx2Change,
|
||||||
|
|
@ -208,7 +212,7 @@ export const AdvancedTab = () => {
|
||||||
<Group mb="xs" justify="space-between">
|
<Group mb="xs" justify="space-between">
|
||||||
<Group>
|
<Group>
|
||||||
<Text size="sm" fw={500}>
|
<Text size="sm" fw={500}>
|
||||||
Additional arguments
|
Additional Arguments
|
||||||
</Text>
|
</Text>
|
||||||
<InfoTooltip label="Additional command line arguments to pass to the 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>
|
</Group>
|
||||||
|
|
@ -229,6 +233,57 @@ export const AdvancedTab = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Group mb="xs">
|
||||||
|
<Text size="sm" fw={500}>
|
||||||
|
Pre-Launch Commands
|
||||||
|
</Text>
|
||||||
|
<InfoTooltip label="Shell commands to run before launching. Useful for starting local services or custom APIs." />
|
||||||
|
</Group>
|
||||||
|
<Stack gap="xs">
|
||||||
|
{preLaunchCommands.map((command, index) => (
|
||||||
|
<Group key={index} gap="xs">
|
||||||
|
<TextInput
|
||||||
|
placeholder="Enter a shell command"
|
||||||
|
value={command}
|
||||||
|
onChange={(event) => {
|
||||||
|
const newCommands = [...preLaunchCommands];
|
||||||
|
newCommands[index] = event.currentTarget.value;
|
||||||
|
handlePreLaunchCommandsChange(newCommands);
|
||||||
|
}}
|
||||||
|
style={{ flex: 1 }}
|
||||||
|
/>
|
||||||
|
<ActionIcon
|
||||||
|
variant="subtle"
|
||||||
|
color="red"
|
||||||
|
disabled={preLaunchCommands.length === 1}
|
||||||
|
onClick={() => {
|
||||||
|
const newCommands = preLaunchCommands.filter(
|
||||||
|
(_, i) => i !== index
|
||||||
|
);
|
||||||
|
handlePreLaunchCommandsChange(
|
||||||
|
newCommands.length === 0 ? [''] : newCommands
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Trash2 size={16} />
|
||||||
|
</ActionIcon>
|
||||||
|
</Group>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
variant="subtle"
|
||||||
|
size="xs"
|
||||||
|
leftSection={<Plus size={14} />}
|
||||||
|
onClick={() => {
|
||||||
|
handlePreLaunchCommandsChange([...preLaunchCommands, '']);
|
||||||
|
}}
|
||||||
|
style={{ alignSelf: 'flex-start' }}
|
||||||
|
>
|
||||||
|
Add Command
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</div>
|
||||||
|
|
||||||
<CommandLineArgumentsModal
|
<CommandLineArgumentsModal
|
||||||
opened={commandLineModalOpen}
|
opened={commandLineModalOpen}
|
||||||
onClose={() => setCommandLineModalOpen(false)}
|
onClose={() => setCommandLineModalOpen(false)}
|
||||||
|
|
|
||||||
|
|
@ -796,7 +796,7 @@ export const CommandLineArgumentsModal = ({
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Text size="sm" c="dimmed">
|
<Text size="sm" c="dimmed">
|
||||||
These are additional command line arguments that can be added to the
|
These are additional command line arguments that can be added to the
|
||||||
"Additional Arguments" field.
|
"Additional Arguments" input field.
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
contextSize,
|
contextSize,
|
||||||
model,
|
model,
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
|
preLaunchCommands,
|
||||||
port,
|
port,
|
||||||
host,
|
host,
|
||||||
multiuser,
|
multiuser,
|
||||||
|
|
@ -159,6 +160,7 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
contextsize: contextSize,
|
contextsize: contextSize,
|
||||||
model,
|
model,
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
|
preLaunchCommands: preLaunchCommands.filter((cmd) => cmd.trim() !== ''),
|
||||||
port,
|
port,
|
||||||
host,
|
host,
|
||||||
multiuser: multiuser ? 1 : 0,
|
multiuser: multiuser ? 1 : 0,
|
||||||
|
|
@ -301,6 +303,7 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
usemmap,
|
usemmap,
|
||||||
debugmode,
|
debugmode,
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
|
preLaunchCommands,
|
||||||
sdt5xxl,
|
sdt5xxl,
|
||||||
sdclipl,
|
sdclipl,
|
||||||
sdclipg,
|
sdclipg,
|
||||||
|
|
@ -338,6 +341,7 @@ export const LaunchScreen = ({ onLaunch }: LaunchScreenProps) => {
|
||||||
usemmap,
|
usemmap,
|
||||||
debugmode,
|
debugmode,
|
||||||
additionalArguments,
|
additionalArguments,
|
||||||
|
preLaunchCommands,
|
||||||
sdt5xxl,
|
sdt5xxl,
|
||||||
sdclipl,
|
sdclipl,
|
||||||
sdclipg,
|
sdclipg,
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,9 @@ export const AppearanceTab = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg" h="100%">
|
<Stack gap="lg" h="100%">
|
||||||
<div>
|
|
||||||
<FrontendInterfaceSelector isOnInterfaceScreen={isOnInterfaceScreen} />
|
<FrontendInterfaceSelector isOnInterfaceScreen={isOnInterfaceScreen} />
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
Theme
|
Theme
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
|
|
@ -138,7 +136,7 @@ export const AppearanceTab = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
Zoom Level
|
Zoom Level
|
||||||
</Text>
|
</Text>
|
||||||
<Group justify="space-between" align="center" mb="md">
|
<Group justify="space-between" align="center" mb="md">
|
||||||
|
|
|
||||||
|
|
@ -223,13 +223,15 @@ export const FrontendInterfaceSelector = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Text fw={500} mb="sm">
|
<div>
|
||||||
|
<Text fw={500} mb="xs">
|
||||||
Frontend Interface
|
Frontend Interface
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{getUnmetRequirements().length === 0 && (
|
{getUnmetRequirements().length === 0 && (
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
Choose which frontend interface to use for interacting with AI models
|
Choose which frontend interface to use for interacting with AI
|
||||||
|
models
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -267,8 +269,10 @@ export const FrontendInterfaceSelector = ({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{renderDisabledFrontendWarnings()}
|
{renderDisabledFrontendWarnings()}
|
||||||
|
</div>
|
||||||
|
|
||||||
<Text fw={500} mb="sm" mt="xl">
|
<div>
|
||||||
|
<Text fw={500} mb="xs">
|
||||||
Image Generation Frontend
|
Image Generation Frontend
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
@ -286,6 +290,7 @@ export const FrontendInterfaceSelector = ({
|
||||||
]}
|
]}
|
||||||
leftSection={<Image style={{ width: rem(16), height: rem(16) }} />}
|
leftSection={<Image style={{ width: rem(16), height: rem(16) }} />}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export const GeneralTab = () => {
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg" h="100%">
|
<Stack gap="lg" h="100%">
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
Status Bar
|
Status Bar
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
|
|
@ -41,7 +41,7 @@ export const GeneralTab = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
System Tray
|
System Tray
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export const TroubleshootingTab = () => {
|
||||||
return (
|
return (
|
||||||
<Stack gap="lg" h="100%">
|
<Stack gap="lg" h="100%">
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
Installation Directory
|
Installation Directory
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
|
|
@ -70,7 +70,7 @@ export const TroubleshootingTab = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Text fw={500} mb="sm">
|
<Text fw={500} mb="xs">
|
||||||
Diagnostics
|
Diagnostics
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" c="dimmed" mb="md">
|
<Text size="sm" c="dimmed" mb="md">
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ export const useLaunchConfig = () => {
|
||||||
contextSize: state.contextSize,
|
contextSize: state.contextSize,
|
||||||
model: state.model,
|
model: state.model,
|
||||||
additionalArguments: state.additionalArguments,
|
additionalArguments: state.additionalArguments,
|
||||||
|
preLaunchCommands: state.preLaunchCommands,
|
||||||
port: state.port,
|
port: state.port,
|
||||||
host: state.host,
|
host: state.host,
|
||||||
multiuser: state.multiuser,
|
multiuser: state.multiuser,
|
||||||
|
|
@ -65,6 +66,7 @@ export const useLaunchConfig = () => {
|
||||||
handleQuantmatmulChange: state.setQuantmatmul,
|
handleQuantmatmulChange: state.setQuantmatmul,
|
||||||
handleUsemmapChange: state.setUsemmap,
|
handleUsemmapChange: state.setUsemmap,
|
||||||
handleDebugmodeChange: state.setDebugmode,
|
handleDebugmodeChange: state.setDebugmode,
|
||||||
|
handlePreLaunchCommandsChange: state.setPreLaunchCommands,
|
||||||
handleBackendChange: state.setBackend,
|
handleBackendChange: state.setBackend,
|
||||||
handleGpuDeviceSelectionChange: state.setGpuDeviceSelection,
|
handleGpuDeviceSelectionChange: state.setGpuDeviceSelection,
|
||||||
handleTensorSplitChange: state.setTensorSplit,
|
handleTensorSplitChange: state.setTensorSplit,
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ interface LaunchArgs {
|
||||||
usemmap: boolean;
|
usemmap: boolean;
|
||||||
debugmode: boolean;
|
debugmode: boolean;
|
||||||
additionalArguments: string;
|
additionalArguments: string;
|
||||||
|
preLaunchCommands: string[];
|
||||||
sdt5xxl: string;
|
sdt5xxl: string;
|
||||||
sdclipl: string;
|
sdclipl: string;
|
||||||
sdclipg: string;
|
sdclipg: string;
|
||||||
|
|
@ -283,7 +284,14 @@ export const useLaunchLogic = ({
|
||||||
args.push(...additionalArgs);
|
args.push(...additionalArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await window.electronAPI.kobold.launchKoboldCpp(args);
|
const preLaunchCommands = launchArgs.preLaunchCommands.filter(
|
||||||
|
(cmd) => cmd.trim() !== ''
|
||||||
|
);
|
||||||
|
|
||||||
|
const result = await window.electronAPI.kobold.launchKoboldCpp(
|
||||||
|
args,
|
||||||
|
preLaunchCommands
|
||||||
|
);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
onLaunch();
|
onLaunch();
|
||||||
|
|
|
||||||
|
|
@ -135,8 +135,8 @@ export function setupIPCHandlers() {
|
||||||
|
|
||||||
ipcMain.handle('kobold:getPlatform', () => platform);
|
ipcMain.handle('kobold:getPlatform', () => platform);
|
||||||
|
|
||||||
ipcMain.handle('kobold:launchKoboldCpp', (_, args) =>
|
ipcMain.handle('kobold:launchKoboldCpp', (_, args, preLaunchCommands) =>
|
||||||
launchKoboldCppWithCustomFrontends(args)
|
launchKoboldCppWithCustomFrontends(args, preLaunchCommands)
|
||||||
);
|
);
|
||||||
|
|
||||||
ipcMain.handle('kobold:deleteRelease', (_, binaryPath) =>
|
ipcMain.handle('kobold:deleteRelease', (_, binaryPath) =>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { spawn, ChildProcess } from 'child_process';
|
import { spawn, ChildProcess } from 'child_process';
|
||||||
|
import { platform } from 'process';
|
||||||
|
|
||||||
import { terminateProcess } from '@/utils/node/process';
|
import { terminateProcess } from '@/utils/node/process';
|
||||||
import { logError, safeExecute } from '@/utils/node/logging';
|
import { logError, safeExecute } from '@/utils/node/logging';
|
||||||
|
|
@ -10,6 +11,7 @@ import { getCurrentVersion } from '../version';
|
||||||
import {
|
import {
|
||||||
getCurrentKoboldBinary,
|
getCurrentKoboldBinary,
|
||||||
get as getConfig,
|
get as getConfig,
|
||||||
|
getInstallDir,
|
||||||
} from '@/main/modules/config';
|
} from '@/main/modules/config';
|
||||||
import { startFrontend as startSillyTavernFrontend } from '@/main/modules/sillytavern';
|
import { startFrontend as startSillyTavernFrontend } from '@/main/modules/sillytavern';
|
||||||
import { startFrontend as startOpenWebUIFrontend } from '@/main/modules/openwebui';
|
import { startFrontend as startOpenWebUIFrontend } from '@/main/modules/openwebui';
|
||||||
|
|
@ -23,6 +25,70 @@ import type {
|
||||||
} from '@/types';
|
} from '@/types';
|
||||||
|
|
||||||
let koboldProcess: ChildProcess | null = null;
|
let koboldProcess: ChildProcess | null = null;
|
||||||
|
const preLaunchProcesses = new Set<ChildProcess>();
|
||||||
|
|
||||||
|
function spawnPreLaunchCommands(commands: string[]) {
|
||||||
|
const installDir = getInstallDir();
|
||||||
|
const shell = platform === 'win32' ? 'cmd' : '/bin/sh';
|
||||||
|
const shellFlag = platform === 'win32' ? '/c' : '-c';
|
||||||
|
|
||||||
|
for (const command of commands) {
|
||||||
|
if (!command.trim()) continue;
|
||||||
|
|
||||||
|
sendKoboldOutput(`[PRE-LAUNCH] Running: ${command}\n`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const child = spawn(shell, [shellFlag, command], {
|
||||||
|
cwd: installDir,
|
||||||
|
stdio: ['ignore', 'pipe', 'pipe'],
|
||||||
|
detached: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
preLaunchProcesses.add(child);
|
||||||
|
|
||||||
|
child.stdout?.on('data', (data) => {
|
||||||
|
sendKoboldOutput(`[PRE-LAUNCH] ${data.toString()}`, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.stderr?.on('data', (data) => {
|
||||||
|
sendKoboldOutput(`[PRE-LAUNCH] ${data.toString()}`, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('error', (error) => {
|
||||||
|
sendKoboldOutput(
|
||||||
|
`[PRE-LAUNCH ERROR] Failed to run "${command}": ${error.message}\n`
|
||||||
|
);
|
||||||
|
preLaunchProcesses.delete(child);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('exit', (code, signal) => {
|
||||||
|
preLaunchProcesses.delete(child);
|
||||||
|
if (code !== 0 && code !== null) {
|
||||||
|
sendKoboldOutput(
|
||||||
|
`[PRE-LAUNCH] Command "${command}" exited with code ${code}\n`
|
||||||
|
);
|
||||||
|
} else if (signal) {
|
||||||
|
sendKoboldOutput(
|
||||||
|
`[PRE-LAUNCH] Command "${command}" terminated with signal ${signal}\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
sendKoboldOutput(
|
||||||
|
`[PRE-LAUNCH ERROR] Failed to start "${command}": ${error instanceof Error ? error.message : String(error)}\n`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stopPreLaunchProcesses() {
|
||||||
|
const terminations = Array.from(preLaunchProcesses).map((process) =>
|
||||||
|
terminateProcess(process)
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(terminations);
|
||||||
|
preLaunchProcesses.clear();
|
||||||
|
}
|
||||||
|
|
||||||
async function resolveModelPaths(args: string[]) {
|
async function resolveModelPaths(args: string[]) {
|
||||||
const resolvedArgs: string[] = [];
|
const resolvedArgs: string[] = [];
|
||||||
|
|
@ -75,13 +141,18 @@ async function resolveModelPaths(args: string[]) {
|
||||||
export async function launchKoboldCpp(
|
export async function launchKoboldCpp(
|
||||||
args: string[] = [],
|
args: string[] = [],
|
||||||
frontendPreference: FrontendPreference = 'koboldcpp',
|
frontendPreference: FrontendPreference = 'koboldcpp',
|
||||||
imageGenerationFrontendPreference?: ImageGenerationFrontendPreference
|
imageGenerationFrontendPreference?: ImageGenerationFrontendPreference,
|
||||||
|
preLaunchCommands: string[] = []
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
if (koboldProcess) {
|
if (koboldProcess) {
|
||||||
await stopKoboldCpp();
|
await stopKoboldCpp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preLaunchCommands.length > 0) {
|
||||||
|
spawnPreLaunchCommands(preLaunchCommands);
|
||||||
|
}
|
||||||
|
|
||||||
const currentVersion = await getCurrentVersion();
|
const currentVersion = await getCurrentVersion();
|
||||||
if (!currentVersion || !(await pathExists(currentVersion.path))) {
|
if (!currentVersion || !(await pathExists(currentVersion.path))) {
|
||||||
const rawPath = getCurrentKoboldBinary();
|
const rawPath = getCurrentKoboldBinary();
|
||||||
|
|
@ -213,11 +284,15 @@ export async function launchKoboldCpp(
|
||||||
|
|
||||||
export async function stopKoboldCpp() {
|
export async function stopKoboldCpp() {
|
||||||
abortActiveDownloads();
|
abortActiveDownloads();
|
||||||
await stopProxy();
|
stopProxy();
|
||||||
|
stopPreLaunchProcesses();
|
||||||
return terminateProcess(koboldProcess);
|
return terminateProcess(koboldProcess);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const launchKoboldCppWithCustomFrontends = async (args: string[] = []) =>
|
export const launchKoboldCppWithCustomFrontends = async (
|
||||||
|
args: string[] = [],
|
||||||
|
preLaunchCommands: string[] = []
|
||||||
|
) =>
|
||||||
safeExecute(async () => {
|
safeExecute(async () => {
|
||||||
const [frontendPreference, imageGenerationFrontendPreference] =
|
const [frontendPreference, imageGenerationFrontendPreference] =
|
||||||
(await Promise.all([
|
(await Promise.all([
|
||||||
|
|
@ -233,7 +308,8 @@ export const launchKoboldCppWithCustomFrontends = async (args: string[] = []) =>
|
||||||
const result = await launchKoboldCpp(
|
const result = await launchKoboldCpp(
|
||||||
args,
|
args,
|
||||||
frontendPreference,
|
frontendPreference,
|
||||||
imageGenerationFrontendPreference
|
imageGenerationFrontendPreference,
|
||||||
|
preLaunchCommands
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,8 @@ const koboldAPI: KoboldAPI = {
|
||||||
ipcRenderer.invoke('kobold:downloadRelease', asset, options),
|
ipcRenderer.invoke('kobold:downloadRelease', asset, options),
|
||||||
deleteRelease: (binaryPath) =>
|
deleteRelease: (binaryPath) =>
|
||||||
ipcRenderer.invoke('kobold:deleteRelease', binaryPath),
|
ipcRenderer.invoke('kobold:deleteRelease', binaryPath),
|
||||||
launchKoboldCpp: (args) => ipcRenderer.invoke('kobold:launchKoboldCpp', args),
|
launchKoboldCpp: (args, preLaunchCommands) =>
|
||||||
|
ipcRenderer.invoke('kobold:launchKoboldCpp', args, preLaunchCommands),
|
||||||
getConfigFiles: () => ipcRenderer.invoke('kobold:getConfigFiles'),
|
getConfigFiles: () => ipcRenderer.invoke('kobold:getConfigFiles'),
|
||||||
saveConfigFile: (configName, configData) =>
|
saveConfigFile: (configName, configData) =>
|
||||||
ipcRenderer.invoke('kobold:saveConfigFile', configName, configData),
|
ipcRenderer.invoke('kobold:saveConfigFile', configName, configData),
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ interface LaunchConfigState {
|
||||||
contextSize: number;
|
contextSize: number;
|
||||||
model: string;
|
model: string;
|
||||||
additionalArguments: string;
|
additionalArguments: string;
|
||||||
|
preLaunchCommands: string[];
|
||||||
port?: number;
|
port?: number;
|
||||||
host: string;
|
host: string;
|
||||||
multiuser: boolean;
|
multiuser: boolean;
|
||||||
|
|
@ -63,6 +64,7 @@ interface LaunchConfigState {
|
||||||
setQuantmatmul: (quantmatmul: boolean) => void;
|
setQuantmatmul: (quantmatmul: boolean) => void;
|
||||||
setUsemmap: (usemmap: boolean) => void;
|
setUsemmap: (usemmap: boolean) => void;
|
||||||
setDebugmode: (debugmode: boolean) => void;
|
setDebugmode: (debugmode: boolean) => void;
|
||||||
|
setPreLaunchCommands: (commands: string[]) => void;
|
||||||
setBackend: (backend: string) => void;
|
setBackend: (backend: string) => void;
|
||||||
setGpuDeviceSelection: (selection: string) => void;
|
setGpuDeviceSelection: (selection: string) => void;
|
||||||
setTensorSplit: (split: string) => void;
|
setTensorSplit: (split: string) => void;
|
||||||
|
|
@ -103,6 +105,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
contextSize: DEFAULT_CONTEXT_SIZE,
|
contextSize: DEFAULT_CONTEXT_SIZE,
|
||||||
model: '',
|
model: '',
|
||||||
additionalArguments: '',
|
additionalArguments: '',
|
||||||
|
preLaunchCommands: [''],
|
||||||
port: undefined,
|
port: undefined,
|
||||||
host: '',
|
host: '',
|
||||||
multiuser: false,
|
multiuser: false,
|
||||||
|
|
@ -162,6 +165,7 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
setQuantmatmul: (quantmatmul) => set({ quantmatmul }),
|
setQuantmatmul: (quantmatmul) => set({ quantmatmul }),
|
||||||
setUsemmap: (usemmap) => set({ usemmap }),
|
setUsemmap: (usemmap) => set({ usemmap }),
|
||||||
setDebugmode: (debugmode) => set({ debugmode }),
|
setDebugmode: (debugmode) => set({ debugmode }),
|
||||||
|
setPreLaunchCommands: (commands) => set({ preLaunchCommands: commands }),
|
||||||
setBackend: (backend) =>
|
setBackend: (backend) =>
|
||||||
set({
|
set({
|
||||||
backend,
|
backend,
|
||||||
|
|
@ -225,6 +229,16 @@ export const useLaunchConfigStore = create<LaunchConfigState>((set, get) => ({
|
||||||
updates.additionalArguments = '';
|
updates.additionalArguments = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(configData.preLaunchCommands)) {
|
||||||
|
const filteredCommands = configData.preLaunchCommands.filter(
|
||||||
|
(cmd): cmd is string => typeof cmd === 'string'
|
||||||
|
);
|
||||||
|
updates.preLaunchCommands =
|
||||||
|
filteredCommands.length === 0 ? [''] : filteredCommands;
|
||||||
|
} else {
|
||||||
|
updates.preLaunchCommands = [''];
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof configData.port === 'number') {
|
if (typeof configData.port === 'number') {
|
||||||
updates.port = configData.port;
|
updates.port = configData.port;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
4
src/types/electron.d.ts
vendored
4
src/types/electron.d.ts
vendored
|
|
@ -116,6 +116,7 @@ export interface KoboldConfig {
|
||||||
sdvaecpu?: boolean;
|
sdvaecpu?: boolean;
|
||||||
sdclipgpu?: boolean;
|
sdclipgpu?: boolean;
|
||||||
additionalArguments?: string;
|
additionalArguments?: string;
|
||||||
|
preLaunchCommands?: string[];
|
||||||
moecpu?: number;
|
moecpu?: number;
|
||||||
moeexperts?: number;
|
moeexperts?: number;
|
||||||
autoGpuLayers?: boolean;
|
autoGpuLayers?: boolean;
|
||||||
|
|
@ -146,7 +147,8 @@ export interface KoboldAPI {
|
||||||
binaryPath: string
|
binaryPath: string
|
||||||
) => Promise<{ success: boolean; error?: string }>;
|
) => Promise<{ success: boolean; error?: string }>;
|
||||||
launchKoboldCpp: (
|
launchKoboldCpp: (
|
||||||
args?: string[]
|
args?: string[],
|
||||||
|
preLaunchCommands?: string[]
|
||||||
) => Promise<{ success: boolean; pid?: number; error?: string }>;
|
) => Promise<{ success: boolean; pid?: number; error?: string }>;
|
||||||
getConfigFiles: () => Promise<{ name: string; path: string; size: number }[]>;
|
getConfigFiles: () => Promise<{ name: string; path: string; size: number }[]>;
|
||||||
saveConfigFile: (
|
saveConfigFile: (
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue