minor fixes and improvements

This commit is contained in:
Egor 2025-08-20 01:02:43 -07:00
parent 9dec99b4cc
commit f2aaa6ff4c
13 changed files with 51 additions and 60 deletions

View file

@ -1 +1 @@
npx lint-staged yarn dlx lint-staged

View file

@ -1,7 +1,7 @@
{ {
"name": "friendly-kobold", "name": "friendly-kobold",
"productName": "Friendly Kobold", "productName": "Friendly Kobold",
"version": "0.3.1", "version": "0.3.2",
"description": "A modern Electron shell for KoboldCpp", "description": "A modern Electron shell for KoboldCpp",
"main": "out/main/index.js", "main": "out/main/index.js",
"homepage": "./", "homepage": "./",
@ -26,7 +26,7 @@
"spell-check": "cspell \"**/*.{ts,tsx,js,jsx,md,json}\" --no-progress", "spell-check": "cspell \"**/*.{ts,tsx,js,jsx,md,json}\" --no-progress",
"spell-check:fix": "cspell \"**/*.{ts,tsx,js,jsx,md,json}\" --no-progress --show-suggestions", "spell-check:fix": "cspell \"**/*.{ts,tsx,js,jsx,md,json}\" --no-progress --show-suggestions",
"check-all": "yarn lint && yarn compile && yarn spell-check", "check-all": "yarn lint && yarn compile && yarn spell-check",
"release": "node scripts/release.js", "release": "yarn dlx tsx scripts/release.ts",
"prepare": "husky" "prepare": "husky"
}, },
"lint-staged": { "lint-staged": {

View file

@ -1,22 +1,24 @@
#!/usr/bin/env node #!/usr/bin/env tsx
const { execSync } = require('child_process'); import { execSync } from 'child_process';
const fs = require('fs'); import { readFileSync } from 'fs';
const path = require('path'); import { join } from 'path';
// Read package.json to get current version interface PackageJson {
const packageJson = JSON.parse( version: string;
fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8') [key: string]: unknown;
}
const packageJson: PackageJson = JSON.parse(
readFileSync(join(__dirname, '..', 'package.json'), 'utf8')
); );
const currentVersion = packageJson.version; const currentVersion = packageJson.version;
console.log(`Creating release for version ${currentVersion}...`); console.log(`Creating release for version ${currentVersion}...`);
try { try {
// Check if we're in a git repository
execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
// Check if there are uncommitted changes
const gitStatus = execSync('git status --porcelain', { encoding: 'utf8' }); const gitStatus = execSync('git status --porcelain', { encoding: 'utf8' });
if (gitStatus.trim() !== '') { if (gitStatus.trim() !== '') {
console.error( console.error(
@ -25,7 +27,6 @@ try {
process.exit(1); process.exit(1);
} }
// Create and push the tag
const tagName = `v${currentVersion}`; const tagName = `v${currentVersion}`;
console.log(`Creating tag ${tagName}...`); console.log(`Creating tag ${tagName}...`);
@ -39,7 +40,8 @@ try {
console.log( console.log(
`🔗 Check the progress at: https://github.com/lone-cloud/friendly-kobold/actions` `🔗 Check the progress at: https://github.com/lone-cloud/friendly-kobold/actions`
); );
} catch (error) { } catch (error: unknown) {
console.error('❌ Error creating release:', error.message); const errorMessage = error instanceof Error ? error.message : String(error);
console.error('❌ Error creating release:', errorMessage);
process.exit(1); process.exit(1);
} }

View file

@ -20,7 +20,7 @@ export const BackendSelectItem = forwardRef<
<Group gap={4}> <Group gap={4}>
{devices.slice(0, 2).map((device, index) => ( {devices.slice(0, 2).map((device, index) => (
<Badge key={index} size="md" variant="light" color="blue"> <Badge key={index} size="md" variant="light" color="blue">
{device.length > 18 ? `${device.slice(0, 18)}...` : device} {device.length > 25 ? `${device.slice(0, 25)}...` : device}
</Badge> </Badge>
))} ))}
{devices.length > 2 && ( {devices.length > 2 && (

View file

@ -132,8 +132,6 @@ export const LaunchScreen = ({
}); });
const { isLaunching, handleLaunch } = useLaunchLogic({ const { isLaunching, handleLaunch } = useLaunchLogic({
configFiles,
selectedFile,
modelPath, modelPath,
sdmodel, sdmodel,
onLaunch, onLaunch,

View file

@ -9,7 +9,6 @@ import {
DEFAULT_MODEL_URL, DEFAULT_MODEL_URL,
DEFAULT_HOST, DEFAULT_HOST,
} from '@/constants'; } from '@/constants';
import { isNotNullish } from '@/utils';
export const useLaunchConfig = () => { export const useLaunchConfig = () => {
const [gpuLayers, setGpuLayers] = useState<number>(0); const [gpuLayers, setGpuLayers] = useState<number>(0);
@ -137,7 +136,7 @@ export const useLaunchConfig = () => {
setQuantmatmul(configData.quantmatmul); setQuantmatmul(configData.quantmatmul);
} }
if (isNotNullish(configData.usecuda)) { if (configData.usecuda === true) {
const gpuInfo = await window.electronAPI.kobold.detectGPU(); const gpuInfo = await window.electronAPI.kobold.detectGPU();
setBackend(gpuInfo.hasNVIDIA ? 'cuda' : 'rocm'); setBackend(gpuInfo.hasNVIDIA ? 'cuda' : 'rocm');
@ -150,9 +149,9 @@ export const useLaunchConfig = () => {
setGpuDevice(parseInt(deviceId, 10) || 0); setGpuDevice(parseInt(deviceId, 10) || 0);
setQuantmatmul(mmqMode === 'mmq'); setQuantmatmul(mmqMode === 'mmq');
} }
} else if (isNotNullish(configData.usevulkan)) { } else if (configData.usevulkan === true) {
setBackend('vulkan'); setBackend('vulkan');
} else if (isNotNullish(configData.useclblast)) { } else if (configData.useclblast === true) {
setBackend('clblast'); setBackend('clblast');
} else { } else {
setBackend('cpu'); setBackend('cpu');

View file

@ -1,9 +1,6 @@
import { useState, useCallback } from 'react'; import { useState, useCallback } from 'react';
import type { ConfigFile } from '@/types';
interface UseLaunchLogicProps { interface UseLaunchLogicProps {
configFiles: ConfigFile[];
selectedFile: string | null;
modelPath: string; modelPath: string;
sdmodel: string; sdmodel: string;
onLaunch: () => void; onLaunch: () => void;
@ -133,8 +130,6 @@ const buildBackendArgs = (launchArgs: LaunchArgs): string[] => {
}; };
export const useLaunchLogic = ({ export const useLaunchLogic = ({
configFiles,
selectedFile,
modelPath, modelPath,
sdmodel, sdmodel,
onLaunch, onLaunch,
@ -154,10 +149,6 @@ export const useLaunchLogic = ({
setIsLaunching(true); setIsLaunching(true);
try { try {
const selectedConfig = selectedFile
? configFiles.find((f) => f.name === selectedFile)
: null;
const args: string[] = [ const args: string[] = [
...buildModelArgs( ...buildModelArgs(
isImageMode, isImageMode,
@ -177,10 +168,7 @@ export const useLaunchLogic = ({
args.push(...additionalArgs); args.push(...additionalArgs);
} }
const result = await window.electronAPI.kobold.launchKoboldCpp( const result = await window.electronAPI.kobold.launchKoboldCpp(args);
args,
selectedConfig?.path
);
if (result.success) { if (result.success) {
if (onLaunchModeChange) { if (onLaunchModeChange) {
@ -205,15 +193,7 @@ export const useLaunchLogic = ({
setIsLaunching(false); setIsLaunching(false);
} }
}, },
[ [modelPath, sdmodel, isLaunching, onLaunch, onLaunchModeChange]
configFiles,
selectedFile,
modelPath,
sdmodel,
isLaunching,
onLaunch,
onLaunchModeChange,
]
); );
return { return {

View file

@ -914,8 +914,7 @@ export class KoboldCppManager {
} }
async launchKoboldCpp( async launchKoboldCpp(
args: string[] = [], args: string[] = []
configFilePath?: string
): Promise<{ success: boolean; pid?: number; error?: string }> { ): Promise<{ success: boolean; pid?: number; error?: string }> {
try { try {
if (this.koboldProcess) { if (this.koboldProcess) {
@ -936,10 +935,6 @@ export class KoboldCppManager {
const finalArgs = [...args]; const finalArgs = [...args];
if (configFilePath && existsSync(configFilePath)) {
finalArgs.push('--config', configFilePath);
}
const child = spawn(currentVersion.path, finalArgs, { const child = spawn(currentVersion.path, finalArgs, {
stdio: ['pipe', 'pipe', 'pipe'], stdio: ['pipe', 'pipe', 'pipe'],
detached: false, detached: false,

View file

@ -1,5 +1,6 @@
/* eslint-disable no-comments/disallowComments */ /* eslint-disable no-comments/disallowComments */
import si from 'systeminformation'; import si from 'systeminformation';
import { shortenDeviceName } from '@/utils';
import type { import type {
CPUCapabilities, CPUCapabilities,
GPUCapabilities, GPUCapabilities,
@ -22,7 +23,7 @@ export class HardwareService {
const devices: string[] = []; const devices: string[] = [];
if (cpu.brand) { if (cpu.brand) {
devices.push(cpu.brand); devices.push(shortenDeviceName(cpu.brand));
} }
const avx = flags.includes('avx') || flags.includes('AVX'); const avx = flags.includes('avx') || flags.includes('AVX');
@ -62,7 +63,7 @@ export class HardwareService {
for (const controller of graphics.controllers) { for (const controller of graphics.controllers) {
if (controller.model) { if (controller.model) {
gpuInfo.push(controller.model); gpuInfo.push(shortenDeviceName(controller.model));
} }
const vendor = controller.vendor?.toLowerCase() || ''; const vendor = controller.vendor?.toLowerCase() || '';
@ -168,7 +169,8 @@ export class HardwareService {
.split('\n') .split('\n')
.map((line) => { .map((line) => {
const parts = line.split(','); const parts = line.split(',');
return parts[0]?.trim() || 'Unknown NVIDIA GPU'; const rawName = parts[0]?.trim() || 'Unknown NVIDIA GPU';
return shortenDeviceName(rawName);
}) })
.filter(Boolean); .filter(Boolean);
@ -248,7 +250,7 @@ export class HardwareService {
} }
if (deviceType !== 'CPU') { if (deviceType !== 'CPU') {
devices.push(name); devices.push(shortenDeviceName(name));
} }
} }
} }
@ -304,7 +306,7 @@ export class HardwareService {
if (line.includes('deviceName')) { if (line.includes('deviceName')) {
const name = line.split('=')[1]?.trim(); const name = line.split('=')[1]?.trim();
if (name) { if (name) {
devices.push(name); devices.push(shortenDeviceName(name));
} }
} }
} }
@ -362,7 +364,7 @@ export class HardwareService {
if (platform.devices) { if (platform.devices) {
for (const device of platform.devices) { for (const device of platform.devices) {
if (device.name && device.type !== 'CPU') { if (device.name && device.type !== 'CPU') {
devices.push(device.name); devices.push(shortenDeviceName(device.name));
} }
} }
} }
@ -381,7 +383,7 @@ export class HardwareService {
if (line.includes('Device Name') && !line.includes('CPU')) { if (line.includes('Device Name') && !line.includes('CPU')) {
const name = line.split(':')[1]?.trim(); const name = line.split(':')[1]?.trim();
if (name) { if (name) {
devices.push(name); devices.push(shortenDeviceName(name));
} }
} }
} }

View file

@ -171,8 +171,8 @@ export class IPCHandlers {
this.koboldManager.getLatestReleaseWithDownloadStatus() this.koboldManager.getLatestReleaseWithDownloadStatus()
); );
ipcMain.handle('kobold:launchKoboldCpp', (_event, args, configFilePath) => ipcMain.handle('kobold:launchKoboldCpp', (_event, args) =>
this.koboldManager.launchKoboldCpp(args, configFilePath) this.koboldManager.launchKoboldCpp(args)
); );
ipcMain.handle('kobold:stopKoboldCpp', () => ipcMain.handle('kobold:stopKoboldCpp', () =>

View file

@ -9,7 +9,7 @@ export const getAssetDescription = (assetName: string): string => {
} }
if (name.endsWith(ASSET_SUFFIXES.OLDPC)) { if (name.endsWith(ASSET_SUFFIXES.OLDPC)) {
return 'Meant for old PCs that cannot normally run the standard build.'; return 'Meant for old PCs that cannot run the standard build.';
} }
if (name.endsWith(ASSET_SUFFIXES.NOCUDA)) { if (name.endsWith(ASSET_SUFFIXES.NOCUDA)) {

14
src/utils/hardware.ts Normal file
View file

@ -0,0 +1,14 @@
export const shortenDeviceName = (deviceName: string): string =>
deviceName
.replace(/^AMD\s+/i, '')
.replace(/^NVIDIA\s+/i, '')
.replace(/^Intel\s+/i, '')
.replace(/\s+Graphics/i, '')
.replace(/\s+GPU/i, '')
.replace(/\s+Processor/i, '')
.replace(/\s+CPU/i, '')
.replace(/GeForce\s+/i, '')
.replace(/Radeon\s+/i, '')
.replace(/\s+Series/i, '')
.replace(/\s+/g, ' ')
.trim();

View file

@ -1,6 +1,7 @@
export * from './assets'; export * from './assets';
export * from './downloadUtils'; export * from './downloadUtils';
export * from './fileSize'; export * from './fileSize';
export * from './hardware';
export * from './imageModelPresets'; export * from './imageModelPresets';
export * from './nullish'; export * from './nullish';
export * from './platform'; export * from './platform';