fix(nix): shrink desktop runtime output (#2550)

Package only the traced desktop and daemon runtime graph, preserve required runtime entrypoints, and exclude the npm Electron distribution supplied by nixpkgs.
This commit is contained in:
Ivan Malison
2026-08-01 01:37:18 +02:00
committed by GitHub
parent b560c1184c
commit b960594d44
2 changed files with 63 additions and 14 deletions
+39 -13
View File
@@ -5,6 +5,7 @@
nodejs_22, nodejs_22,
python3, python3,
makeWrapper, makeWrapper,
autoPatchelfHook,
copyDesktopItems, copyDesktopItems,
makeDesktopItem, makeDesktopItem,
electron, electron,
@@ -69,9 +70,15 @@ buildNpmPackage rec {
python3 # for node-gyp (node-pty) python3 # for node-gyp (node-pty)
makeWrapper makeWrapper
copyDesktopItems copyDesktopItems
]
++ lib.optionals stdenv.hostPlatform.isLinux [
autoPatchelfHook
]; ];
buildInputs = lib.optionals stdenv.hostPlatform.isLinux [ libuv ]; buildInputs = lib.optionals stdenv.hostPlatform.isLinux [
libuv
stdenv.cc.cc.lib # libstdc++ for sherpa-onnx prebuilt binaries
];
dontNpmBuild = true; dontNpmBuild = true;
@@ -108,19 +115,38 @@ buildNpmPackage rec {
mkdir -p $out/share/paseo-desktop $out/bin mkdir -p $out/share/paseo-desktop $out/bin
# Preserve the monorepo layout so main.js's dev-mode path resolution # Materialize only the desktop and daemon runtime graphs. Copying the
# (`__dirname/../../app/dist`, `__dirname/../assets/icon.png`) works # complete monorepo used to ship every build-time dependency (including
# without patching: invoked unpackaged via `electron path/to/main.js`, # Electron, Expo tooling, and cross-platform builder binaries), making the
# `app.isPackaged` is false, so these relative paths are used. # desktop output larger than 2 GiB.
# PASEO_TRACE_DESKTOP=1 node scripts/trace-daemon.mjs > desktop-files.txt
# Copy the entire packages/ tree (not just built artifacts) because npm
# creates workspace symlinks from node_modules/@getpaseo/* into packages/*. while IFS= read -r path; do
# Missing any workspace package leaves dangling symlinks and fails the [ -z "$path" ] && continue
# noBrokenSymlinks output check. The cleanSourceWith filter above already mkdir -p "$out/share/paseo-desktop/$(dirname "$path")"
# drops the big platform-specific things (android/ios, website, tests). cp -a "$path" "$out/share/paseo-desktop/$path"
done < desktop-files.txt
# Keep the same unpackaged monorepo layout expected by main.js.
cp package.json $out/share/paseo-desktop/ cp package.json $out/share/paseo-desktop/
cp -a packages $out/share/paseo-desktop/ mkdir -p $out/share/paseo-desktop/packages/app
cp -a node_modules $out/share/paseo-desktop/ cp -a packages/app/dist $out/share/paseo-desktop/packages/app/
for runtime_path in \
packages/desktop/dist/main.js \
packages/desktop/dist/preload.js \
packages/desktop/dist/features/browser-keyboard/guest-preload.js \
packages/desktop/package.json; do
if [ ! -e "$out/share/paseo-desktop/$runtime_path" ]; then
echo "desktop runtime trace omitted $runtime_path" >&2
exit 1
fi
done
if [ -e $out/share/paseo-desktop/node_modules/electron ]; then
echo "desktop runtime trace included npm Electron" >&2
exit 1
fi
# Skills directory referenced at runtime by some agents # Skills directory referenced at runtime by some agents
if [ -d skills ]; then if [ -d skills ]; then
+24 -1
View File
@@ -28,14 +28,24 @@ const { sherpaPlatformPackageName } = await import(
).href ).href
); );
const traceDesktop = process.env.PASEO_TRACE_DESKTOP === "1";
// Daemon entry points. Workers forked into their own Node processes have // Daemon entry points. Workers forked into their own Node processes have
// independent require trees; nft does not follow fork boundaries, so trace // independent require trees; nft does not follow fork boundaries, so trace
// them separately. // them separately. The desktop derivation opts into tracing its Electron main
// process and preloads as well.
const entries = [ const entries = [
"packages/cli/dist/index.js", "packages/cli/dist/index.js",
"packages/server/dist/scripts/supervisor-entrypoint.js", "packages/server/dist/scripts/supervisor-entrypoint.js",
"packages/server/dist/server/terminal/terminal-worker-process.js", "packages/server/dist/server/terminal/terminal-worker-process.js",
"packages/server/dist/server/server/speech/providers/local/worker-process.js", "packages/server/dist/server/server/speech/providers/local/worker-process.js",
...(traceDesktop
? [
"packages/desktop/dist/main.js",
"packages/desktop/dist/preload.js",
"packages/desktop/dist/features/browser-keyboard/guest-preload.js",
]
: []),
]; ];
// Files read at runtime via fs APIs rather than `require`. nft only // Files read at runtime via fs APIs rather than `require`. nft only
@@ -59,6 +69,16 @@ const additionalInputs = [
// Copy the wrapper plus the host platform package explicitly. // Copy the wrapper plus the host platform package explicitly.
"node_modules/sherpa-onnx-node/**", "node_modules/sherpa-onnx-node/**",
`node_modules/${sherpaPlatformPackageName()}/**`, `node_modules/${sherpaPlatformPackageName()}/**`,
...(traceDesktop
? [
// The unpackaged Nix launcher resolves these beside desktop/dist.
"packages/desktop/package.json",
"packages/desktop/assets/**",
// resolveExternalCliEntrypoint() looks up the workspace through this
// link at runtime; nft traces the target files but not the link.
"node_modules/@getpaseo/cli",
]
: []),
]; ];
// Trace. // Trace.
@@ -83,6 +103,9 @@ const { fileList, warnings } = await nodeFileTrace(entries, {
// tries to walk into them via index files. Belt and suspenders. // tries to walk into them via index files. Belt and suspenders.
"**/*.test.js", "**/*.test.js",
"**/*.e2e.test.js", "**/*.e2e.test.js",
// The Nix desktop package runs under nixpkgs' Electron. Tracing the npm
// package would duplicate the complete Electron distribution in $out.
...(traceDesktop ? ["node_modules/electron/**"] : []),
], ],
}); });