From 0a211b8d8fe5fc624e1aae8070d097cecbbf87c7 Mon Sep 17 00:00:00 2001 From: inman Date: Wed, 29 Apr 2026 11:04:02 +0800 Subject: [PATCH] fix: fall back when external OpenClaw lacks app deps --- electron/utils/paths.ts | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/electron/utils/paths.ts b/electron/utils/paths.ts index f8bacee..7037aaf 100644 --- a/electron/utils/paths.ts +++ b/electron/utils/paths.ts @@ -23,6 +23,15 @@ type OpenClawRuntimeResolution = { let cachedOpenClawRuntime: OpenClawRuntimeResolution | null = null; +// Packages that Zhinian loads from the OpenClaw package context at main-process +// module initialization time. Some user-installed OpenClaw packages are valid +// CLIs but do not include these app-side integration dependencies; selecting +// them would crash before the UI opens. +const REQUIRED_OPENCLAW_CONTEXT_PACKAGES = [ + '@whiskeysockets/baileys', + 'qrcode-terminal', +] as const; + export { quoteForCmd, needsWinShell, @@ -139,6 +148,28 @@ function isValidOpenClawPackageDir(dir: string): boolean { && existsSync(fsPath(join(dir, 'openclaw.mjs'))); } +function hasRequiredOpenClawContextPackages(dir: string): boolean { + if (!isValidOpenClawPackageDir(dir)) return false; + + try { + const runtimeRequire = createRequire(join(realpathSync(fsPath(dir)), 'package.json')); + for (const packageName of REQUIRED_OPENCLAW_CONTEXT_PACKAGES) { + runtimeRequire.resolve(`${packageName}/package.json`); + } + return true; + } catch { + try { + const runtimeRequire = createRequire(join(dir, 'package.json')); + for (const packageName of REQUIRED_OPENCLAW_CONTEXT_PACKAGES) { + runtimeRequire.resolve(`${packageName}/package.json`); + } + return true; + } catch { + return false; + } + } +} + function samePath(left: string, right: string): boolean { try { return realpathSync(fsPath(left)) === realpathSync(fsPath(right)); @@ -219,7 +250,12 @@ function findExternalOpenClawDir(excludedDirs: string[]): string | null { if (seen.has(candidate)) continue; seen.add(candidate); if (excludedDirs.some((excluded) => samePath(candidate, excluded))) continue; - if (isValidOpenClawPackageDir(candidate)) return candidate; + if (!isValidOpenClawPackageDir(candidate)) continue; + if (hasRequiredOpenClawContextPackages(candidate)) return candidate; + logOpenClawRuntime('[openclaw-runtime] Ignoring external OpenClaw installation because required app dependencies are missing', { + candidate, + requiredPackages: REQUIRED_OPENCLAW_CONTEXT_PACKAGES, + }); } return null;