mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-12 08:51:53 +00:00
fix(nix): natively compile and correctly stage node-pty for desktop app
- Add ELECTRON_SKIP_BINARY_DOWNLOAD=1 to nix/lib.nix to prevent offline download failures. - Manually trigger native compilation of node-pty via npm rebuild --build-from-source in buildPhase. - Run stage-native-deps.cjs to copy the natively compiled binary into build/native-deps. - Flatten native-deps and install-stamp.json to the root of the output derivation in installPhase, matching electron-builder's extraResources behavior so main.cjs can find it at process.resourcesPath + '/native-deps/node-pty'. - Add doCheck=true and a strict checkPhase to fail fast if the staged native binary is missing.
This commit is contained in:
parent
046f444ddc
commit
906bee9cf7
4 changed files with 89 additions and 49 deletions
|
|
@ -95,6 +95,7 @@ try {
|
|||
nodePty = require(nodePtyDir)
|
||||
}
|
||||
} catch {
|
||||
console.log(`[terminal] failed to load node-pty from path ${nodePtyDir}`)
|
||||
nodePty = null
|
||||
nodePtyDir = null
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
"profile:main": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron --inspect=9229 .",
|
||||
"profile:main:cpu": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 NODE_OPTIONS=--cpu-prof HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron .",
|
||||
"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 && node scripts/assert-dist-built.cjs",
|
||||
"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",
|
||||
"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",
|
||||
|
|
|
|||
128
nix/desktop.nix
128
nix/desktop.nix
|
|
@ -6,63 +6,99 @@
|
|||
# `HERMES_DESKTOP_HERMES` override env var, so the desktop's resolver
|
||||
# uses our fully wrapped binary at step 4 ("existing Hermes CLI").
|
||||
# No reimplementation of the agent resolution in this wrapper.
|
||||
{ pkgs, lib, stdenv, makeWrapper, hermesNpmLib, electron, hermesAgent, ... }:
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
stdenv,
|
||||
makeWrapper,
|
||||
hermesNpmLib,
|
||||
electron,
|
||||
hermesAgent,
|
||||
...
|
||||
}:
|
||||
let
|
||||
npm = hermesNpmLib.mkNpmPassthru { folder = "apps/desktop"; attr = "desktop"; pname = "hermes-desktop"; };
|
||||
npm = hermesNpmLib.mkNpmPassthru {
|
||||
folder = "apps/desktop";
|
||||
attr = "desktop";
|
||||
pname = "hermes-desktop";
|
||||
};
|
||||
|
||||
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/apps/desktop/package.json"));
|
||||
version = packageJson.version;
|
||||
|
||||
# Build the renderer (dist/ + electron/ + package.json).
|
||||
renderer = pkgs.buildNpmPackage (npm // {
|
||||
pname = "hermes-desktop-renderer";
|
||||
inherit version;
|
||||
renderer = pkgs.buildNpmPackage (
|
||||
npm
|
||||
// {
|
||||
pname = "hermes-desktop-renderer";
|
||||
inherit version;
|
||||
doCheck = true;
|
||||
|
||||
doCheck = false;
|
||||
# The workspace lockfile resolves all peer deps
|
||||
# correctly so --legacy-peer-deps is not needed.
|
||||
# --ignore-scripts comes from mkNpmPassthru (shared).
|
||||
makeCacheWritable = true;
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
# write-build-stamp.cjs replacement. Packaged Electron reads this
|
||||
# at first-launch to pin the install.ps1 git ref; informational in
|
||||
# nix builds (the backend comes from the derivation directly).
|
||||
mkdir -p apps/desktop/build
|
||||
echo '{"schemaVersion":1,"commit":"nix","branch":"nix","dirty":false,"source":"nix"}' > apps/desktop/build/install-stamp.json
|
||||
|
||||
# write-build-stamp.cjs replacement. Packaged Electron reads this
|
||||
# at first-launch to pin the install.ps1 git ref; informational in
|
||||
# nix builds (the backend comes from the derivation directly).
|
||||
mkdir -p apps/desktop/build
|
||||
echo '{"schemaVersion":1,"commit":"nix","branch":"nix","dirty":false,"source":"nix"}' > apps/desktop/build/install-stamp.json
|
||||
# patch shebangs in node_modules/.bin so npm exec can find the
|
||||
# nix-store equivalents of /usr/bin/env (which doesn't exist in the sandbox)
|
||||
patchShebangs .
|
||||
|
||||
# Build from apps/desktop/ so vite.config.ts resolves correctly.
|
||||
# The workspace root's node_modules/ is accessible as ../../node_modules/.
|
||||
cd apps/desktop
|
||||
pushd apps/desktop
|
||||
# stage node-pty native binaries into build/native-deps for the final nix output
|
||||
npm rebuild node-pty --build-from-source
|
||||
node scripts/stage-native-deps.cjs
|
||||
|
||||
npm exec tsc -b
|
||||
npm exec vite build
|
||||
popd
|
||||
|
||||
# vite handles TS transpilation via esbuild — no type-checking.
|
||||
# We skip `tsc -b` to avoid type errors in test files that don't
|
||||
# ship in the bundle (real upstream peer-dep version mismatches
|
||||
# in @testing-library/react v16 — not blocking the build).
|
||||
# Call vite directly from root node_modules to avoid npx resolving
|
||||
# through unpatched workspace symlinks.
|
||||
node ../../node_modules/vite/bin/vite.js build --outDir dist
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
# Return to source root so installPhase paths are correct.
|
||||
cd ../..
|
||||
checkPhase = ''
|
||||
runHook preCheck
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
pushd apps/desktop
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
||||
# apps/desktop/build was created before the cd. electron/ is source.
|
||||
cp -r apps/desktop/dist $out/
|
||||
cp -r apps/desktop/electron $out/
|
||||
cp -r apps/desktop/build $out/
|
||||
cp apps/desktop/package.json $out/
|
||||
runHook postInstall
|
||||
'';
|
||||
});
|
||||
npm run postbuild
|
||||
|
||||
# validate staged node-pty native binary is present
|
||||
STAGED_PTY_NODE="./build/native-deps/node-pty/build/Release/pty.node"
|
||||
|
||||
if [ ! -f "$STAGED_PTY_NODE" ]; then
|
||||
echo "FATAL: Missing staged node-pty native binary at $STAGED_PTY_NODE"
|
||||
echo "node-pty must be compiled natively"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popd
|
||||
|
||||
runHook postCheck
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out
|
||||
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
||||
# apps/desktop/build was created before the cd. electron/ is source.
|
||||
cp -rn apps/desktop/dist $out/
|
||||
cp -rn apps/desktop/electron $out/
|
||||
|
||||
# flatten native-deps and install-stamp.json to the root level, exactly like
|
||||
# electron-builder's extraResources does ("from": "build/native-deps", "to": "native-deps")
|
||||
# so main.cjs can find it at process.resourcesPath + '/native-deps/node-pty'
|
||||
cp -rn apps/desktop/build/native-deps $out/
|
||||
cp -n apps/desktop/build/install-stamp.json $out/
|
||||
|
||||
cp -n apps/desktop/package.json $out/
|
||||
runHook postInstall
|
||||
'';
|
||||
}
|
||||
);
|
||||
in
|
||||
|
||||
# Electron wrapper: nixpkgs' electron binary pointed at the renderer dir.
|
||||
|
|
@ -81,6 +117,12 @@ stdenv.mkDerivation {
|
|||
mkdir -p $out/share/hermes-desktop $out/bin
|
||||
cp -r ${renderer}/* $out/share/hermes-desktop/
|
||||
|
||||
# Standard nixpkgs pattern for electron-builder apps: patch process.resourcesPath
|
||||
# to point to the app's directory. In Nix, unpackaged electron defaults this
|
||||
# to the electron distribution's resources path, breaking extraResources lookups.
|
||||
substituteInPlace $out/share/hermes-desktop/electron/main.cjs \
|
||||
--replace-fail "process.resourcesPath" "'$out/share/hermes-desktop'"
|
||||
|
||||
# Wrap the nixpkgs electron binary to launch our app. Set
|
||||
# HERMES_DESKTOP_HERMES to the absolute path of the nix-built `hermes`
|
||||
# binary so the desktop's resolver step 4 ("existing Hermes CLI on
|
||||
|
|
|
|||
|
|
@ -65,11 +65,7 @@ in
|
|||
npmRoot = ".";
|
||||
npmDepsFetcherVersion = 2;
|
||||
|
||||
# --ignore-scripts: the workspace includes electron (apps/desktop)
|
||||
# which has a postinstall that tries to download from github.com.
|
||||
# nix builds are offline, so all scripts must be skipped. Each
|
||||
# package sets up its own build commands in buildPhase instead.
|
||||
npmFlags = [ "--ignore-scripts" ];
|
||||
ELECTRON_SKIP_BINARY_DOWNLOAD = 1;
|
||||
|
||||
patchPhase = ''
|
||||
runHook prePatch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue