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",
"productName": "Friendly Kobold",
"version": "0.3.1",
"version": "0.3.2",
"description": "A modern Electron shell for KoboldCpp",
"main": "out/main/index.js",
"homepage": "./",
@ -26,7 +26,7 @@
"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",
"check-all": "yarn lint && yarn compile && yarn spell-check",
"release": "node scripts/release.js",
"release": "yarn dlx tsx scripts/release.ts",
"prepare": "husky"
},
"lint-staged": {

View file

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

View file

@ -20,7 +20,7 @@ export const BackendSelectItem = forwardRef<
<Group gap={4}>
{devices.slice(0, 2).map((device, index) => (
<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>
))}
{devices.length > 2 && (

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,7 +9,7 @@ export const getAssetDescription = (assetName: string): string => {
}
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)) {

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 './downloadUtils';
export * from './fileSize';
export * from './hardware';
export * from './imageModelPresets';
export * from './nullish';
export * from './platform';