From f3b32e9f52204ad654d4c43b364a8bfa4a32b520 Mon Sep 17 00:00:00 2001 From: ChasLui Date: Thu, 4 Jun 2026 11:22:58 +0800 Subject: [PATCH 1/2] fix(desktop): restore Electron binary before macOS pack rename (salvage #38673) electron-builder 26.8.x can stage an Electron.app without its Contents/MacOS/Electron binary, then fail renaming it to Hermes: ENOENT: no such file or directory, rename .../MacOS/Electron -> .../MacOS/Hermes This breaks `npm run pack` and the installer desktop stage before a launchable Hermes.app exists. - Point build.electronDist at the already-installed Electron dist so electron-builder reuses it instead of re-unpacking from cache. - Add a darwin-only prebuilder patch that restores the missing main binary from the runtime dist before the rename. Idempotent (marker guard), soft-fails on shape mismatch, survives node_modules reinstall. Co-authored-by: ChasLui --- apps/desktop/package.json | 2 + .../patch-electron-builder-mac-binary.cjs | 59 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 apps/desktop/scripts/patch-electron-builder-mac-binary.cjs diff --git a/apps/desktop/package.json b/apps/desktop/package.json index 52be586f013..ebc9293668a 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -20,6 +20,7 @@ "start": "npm run build && electron .", "build": "node scripts/assert-root-install.cjs && node scripts/write-build-stamp.cjs && node scripts/stage-native-deps.cjs && tsc -b && vite build && npm run postbuild", "postbuild": "node scripts/assert-dist-built.cjs", + "prebuilder": "node scripts/patch-electron-builder-mac-binary.cjs", "builder": "cross-env NODE_OPTIONS=--max-old-space-size=16384 electron-builder", "pack": "npm run build && npm run builder -- --dir", "dist": "npm run build && npm run builder", @@ -134,6 +135,7 @@ }, "build": { "electronVersion": "40.9.3", + "electronDist": "../../node_modules/electron/dist", "appId": "com.nousresearch.hermes", "productName": "Hermes", "executableName": "Hermes", diff --git a/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs b/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs new file mode 100644 index 00000000000..38315b9c65c --- /dev/null +++ b/apps/desktop/scripts/patch-electron-builder-mac-binary.cjs @@ -0,0 +1,59 @@ +const fs = require('node:fs') +const path = require('node:path') + +if (process.platform !== 'darwin') { + process.exit(0) +} + +const desktopRoot = path.resolve(__dirname, '..') +const repoRoot = path.resolve(desktopRoot, '..', '..') +const electronMacPath = path.join(repoRoot, 'node_modules', 'app-builder-lib', 'out', 'electron', 'electronMac.js') + +const marker = 'hermes-macos-electron-binary-fallback' +const needle = ` await Promise.all([ + doRename(path.join(contentsPath, "MacOS"), electronBranding.productName, appPlist.CFBundleExecutable), + (0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSE")), + (0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSES.chromium.html")), + ]);` +const replacement = ` // ${marker}: electron-builder 26.8.x can sometimes copy + // Electron.app without its main MacOS/Electron binary before this rename. + // Restore it from the installed Electron runtime so local desktop installs + // do not fail with ENOENT during macOS arm64 packaging. + const macosDir = path.join(contentsPath, "MacOS"); + const bundledElectronBinary = path.join(macosDir, electronBranding.productName); + if (!fs.existsSync(bundledElectronBinary)) { + const candidates = [ + path.join(packager.info.framework.distMacOsAppName, "Contents", "MacOS", electronBranding.productName), + path.join(process.cwd(), "..", "..", "node_modules", "electron", "dist", "Electron.app", "Contents", "MacOS", electronBranding.productName), + ]; + const sourceBinary = candidates.find(candidate => fs.existsSync(candidate)); + if (sourceBinary == null) { + throw new Error("Electron binary missing from packaged app and Electron runtime: " + bundledElectronBinary); + } + await (0, promises_1.copyFile)(sourceBinary, bundledElectronBinary); + await (0, promises_1.chmod)(bundledElectronBinary, 0o755); + } + await Promise.all([ + doRename(macosDir, electronBranding.productName, appPlist.CFBundleExecutable), + (0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSE")), + (0, builder_util_1.unlinkIfExists)(path.join(appOutDir, "LICENSES.chromium.html")), + ]);` + +if (!fs.existsSync(electronMacPath)) { + console.warn(`[patch-electron-builder] skipped: ${electronMacPath} not found`) + process.exit(0) +} + +const source = fs.readFileSync(electronMacPath, 'utf8') +if (source.includes(marker)) { + console.log('[patch-electron-builder] macOS Electron binary fallback already applied') + process.exit(0) +} + +if (!source.includes(needle)) { + console.warn('[patch-electron-builder] skipped: expected electronMac.js shape not found') + process.exit(0) +} + +fs.writeFileSync(electronMacPath, source.replace(needle, replacement)) +console.log('[patch-electron-builder] applied macOS Electron binary fallback') From c23a2eec15617c209e0ad28d3b78f41afa74dcd1 Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Mon, 15 Jun 2026 13:53:23 -0500 Subject: [PATCH 2/2] chore: map salvaged contributor email for attribution (#38673) --- scripts/release.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/release.py b/scripts/release.py index 318c8c82d2d..cdebc8e10af 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -45,6 +45,7 @@ ACP_REGISTRY_MANIFEST = REPO_ROOT / "acp_registry" / "agent.json" # Auto-extracted from noreply emails + manual overrides AUTHOR_MAP = { + "chaslui@outlook.com": "ChasLui", "rio.jeong@thebytesize.ai": "rio-jeong", "yehaotian@xuanshudeMac-mini.local": "ArcanePivot", "dbeyer7@gmail.com": "benegessarit",