From 3697ff694e165f2a29c90b81a3c35145538ca602 Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 11 Sep 2025 13:57:24 -0700 Subject: [PATCH] fix sequential awaits and add an eslint rule to catch future ones --- eslint.config.ts | 18 ++++++++++++++++++ package.json | 1 + src/main/index.ts | 28 +++++++++++++++------------- src/main/modules/binary.ts | 21 +++++++++++++++------ src/main/modules/sillytavern.ts | 9 +++++---- yarn.lock | 14 +++++++++++++- 6 files changed, 67 insertions(+), 24 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index f51011a..893d4a4 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -6,7 +6,10 @@ import reactHooks from 'eslint-plugin-react-hooks'; import react from 'eslint-plugin-react'; import importPlugin from 'eslint-plugin-import'; import sonarjs from 'eslint-plugin-sonarjs'; +// @ts-ignore - No types available import noComments from 'eslint-plugin-no-comments'; +// @ts-ignore - No types available +import promise from 'eslint-plugin-promise'; const config = [ js.configs.recommended, @@ -53,6 +56,7 @@ const config = [ import: importPlugin, sonarjs: sonarjs, 'no-comments': noComments, + promise: promise, }, settings: { react: { @@ -155,6 +159,19 @@ const config = [ 'sonarjs/cognitive-complexity': ['warn', 25], + // Promise rules to prevent sequential awaits (no warnings, only errors) + 'promise/prefer-await-to-then': 'error', // Enforce async/await + 'promise/prefer-await-to-callbacks': 'off', // Too aggressive for Electron APIs + 'promise/no-nesting': 'error', // No nested promises + 'promise/no-promise-in-callback': 'off', // Common in Electron + 'promise/no-callback-in-promise': 'off', // Common in Electron + 'promise/avoid-new': 'off', // Sometimes needed for wrapping APIs + 'promise/no-new-statics': 'error', + 'promise/no-return-wrap': 'error', + 'promise/param-names': 'error', + 'promise/catch-or-return': 'off', // Too strict for some patterns + 'promise/no-native': 'off', + 'no-comments/disallowComments': 'error', }, }, @@ -187,6 +204,7 @@ const config = [ '@typescript-eslint/return-await': 'off', '@typescript-eslint/no-unused-vars': 'off', '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-require-imports': 'off', }, }, { diff --git a/package.json b/package.json index 966d55e..b7dd14d 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "eslint": "^9.35.0", "eslint-plugin-import": "^2.32.0", "eslint-plugin-no-comments": "^1.1.10", + "eslint-plugin-promise": "^7.2.1", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-sonarjs": "^3.0.5", diff --git a/src/main/index.ts b/src/main/index.ts index 829df64..335514b 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -17,11 +17,12 @@ if (process.argv[1] === '--version') { process.exit(0); })(); } else { - const isCliMode = process.argv.includes('--cli'); + (async () => { + const isCliMode = process.argv.includes('--cli'); - if (isCliMode) { - import('./cli') - .then(async (cliModule) => { + if (isCliMode) { + try { + const cliModule = await import('./cli'); const args = process.argv.slice(process.argv.indexOf('--cli') + 1); try { await cliModule.handleCliMode(args); @@ -30,18 +31,19 @@ if (process.argv[1] === '--version') { console.error('CLI mode error:', error); process.exit(1); } - }) - .catch((error) => { + } catch (error) { // eslint-disable-next-line no-console console.error('Failed to load CLI module:', error); process.exit(1); - }); - } else { - import('./gui').then((guiModule) => { - guiModule.initializeApp().catch((error: unknown) => { + } + } else { + try { + const guiModule = await import('./gui'); + await guiModule.initializeApp(); + } catch (error: unknown) { // eslint-disable-next-line no-console console.error('Failed to initialize Gerbil:', error); - }); - }); - } + } + } + })(); } diff --git a/src/main/modules/binary.ts b/src/main/modules/binary.ts index d26ba37..c0a8281 100644 --- a/src/main/modules/binary.ts +++ b/src/main/modules/binary.ts @@ -45,12 +45,21 @@ async function detectBackendSupportFromPath(koboldBinaryPath: string) { } }; - support.rocm = await hasKoboldCppLib('koboldcpp_hipblas'); - support.vulkan = await hasKoboldCppLib('koboldcpp_vulkan'); - support.clblast = await hasKoboldCppLib('koboldcpp_clblast'); - support.noavx2 = await hasKoboldCppLib('koboldcpp_noavx2'); - support.failsafe = await hasKoboldCppLib('koboldcpp_failsafe'); - support.cuda = await hasKoboldCppLib('koboldcpp_cublas'); + const [rocm, vulkan, clblast, noavx2, failsafe, cuda] = await Promise.all([ + hasKoboldCppLib('koboldcpp_hipblas'), + hasKoboldCppLib('koboldcpp_vulkan'), + hasKoboldCppLib('koboldcpp_clblast'), + hasKoboldCppLib('koboldcpp_noavx2'), + hasKoboldCppLib('koboldcpp_failsafe'), + hasKoboldCppLib('koboldcpp_cublas'), + ]); + + support.rocm = rocm; + support.vulkan = vulkan; + support.clblast = clblast; + support.noavx2 = noavx2; + support.failsafe = failsafe; + support.cuda = cuda; } catch (error) { logError('Error detecting backend support:', error as Error); } diff --git a/src/main/modules/sillytavern.ts b/src/main/modules/sillytavern.ts index 40c2c0a..29b7188 100644 --- a/src/main/modules/sillytavern.ts +++ b/src/main/modules/sillytavern.ts @@ -480,11 +480,12 @@ export async function stopFrontend() { if (sillyTavernProcess) { promises.push( - terminateProcess(sillyTavernProcess, { - logError: (message, error) => logError(message, error), - }).then(() => { + (async () => { + await terminateProcess(sillyTavernProcess, { + logError: (message, error) => logError(message, error), + }); sillyTavernProcess = null; - }) + })() ); } diff --git a/yarn.lock b/yarn.lock index d230c04..2bfc12e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -584,7 +584,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0": +"@eslint-community/eslint-utils@npm:^4.4.0, @eslint-community/eslint-utils@npm:^4.7.0, @eslint-community/eslint-utils@npm:^4.8.0": version: 4.9.0 resolution: "@eslint-community/eslint-utils@npm:4.9.0" dependencies: @@ -3074,6 +3074,17 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-promise@npm:^7.2.1": + version: 7.2.1 + resolution: "eslint-plugin-promise@npm:7.2.1" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/d494982faeeafbd2aa5fae9cbceca546169a8399000f72d5d940fa5c4ba554612903bcafbb8033647179e5d21ccf1d621b433d089695f7f47ce3d9fcf4cd0abf + languageName: node + linkType: hard + "eslint-plugin-react-hooks@npm:^5.2.0": version: 5.2.0 resolution: "eslint-plugin-react-hooks@npm:5.2.0" @@ -3643,6 +3654,7 @@ __metadata: eslint: "npm:^9.35.0" eslint-plugin-import: "npm:^2.32.0" eslint-plugin-no-comments: "npm:^1.1.10" + eslint-plugin-promise: "npm:^7.2.1" eslint-plugin-react: "npm:^7.37.5" eslint-plugin-react-hooks: "npm:^5.2.0" eslint-plugin-sonarjs: "npm:^3.0.5"