Package the Darwin desktop with electron-builder
This commit is contained in:
+74
-113
@@ -16,57 +16,16 @@
|
|||||||
# the upstream hash via `paseo.override { npmDepsHash = "..."; }`.
|
# the upstream hash via `paseo.override { npmDepsHash = "..."; }`.
|
||||||
paseo,
|
paseo,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
|
||||||
version = (builtins.fromJSON (builtins.readFile ../package.json)).version;
|
|
||||||
darwinInfoPlist = builtins.toFile "Paseo-Info.plist" (
|
|
||||||
lib.generators.toPlist { escape = true; } {
|
|
||||||
CFBundleDisplayName = "Paseo";
|
|
||||||
CFBundleExecutable = "Paseo";
|
|
||||||
CFBundleIconFile = "Paseo.icns";
|
|
||||||
CFBundleIdentifier = "sh.paseo.desktop";
|
|
||||||
CFBundleInfoDictionaryVersion = "6.0";
|
|
||||||
CFBundleName = "Paseo";
|
|
||||||
CFBundlePackageType = "APPL";
|
|
||||||
CFBundleShortVersionString = version;
|
|
||||||
CFBundleURLTypes = [
|
|
||||||
{
|
|
||||||
CFBundleURLName = "Paseo agent link";
|
|
||||||
CFBundleURLSchemes = [ "paseo" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
CFBundleVersion = version;
|
|
||||||
LSApplicationCategoryType = "public.app-category.developer-tools";
|
|
||||||
LSEnvironment.MallocNanoZone = "0";
|
|
||||||
LSMinimumSystemVersion = "12.0";
|
|
||||||
NSAppTransportSecurity.NSAllowsArbitraryLoads = true;
|
|
||||||
NSAudioCaptureUsageDescription = "Paseo needs access to audio capture for voice input.";
|
|
||||||
NSBluetoothAlwaysUsageDescription = "Paseo needs access to Bluetooth audio devices.";
|
|
||||||
NSBluetoothPeripheralUsageDescription = "Paseo needs access to Bluetooth audio devices.";
|
|
||||||
NSCameraUsageDescription = "Paseo needs access to the camera for image attachments.";
|
|
||||||
NSHighResolutionCapable = true;
|
|
||||||
NSMainNibFile = "MainMenu";
|
|
||||||
NSMicrophoneUsageDescription = "Paseo needs access to the microphone for voice input.";
|
|
||||||
NSPrefersDisplaySafeAreaCompatibilityMode = false;
|
|
||||||
NSPrincipalClass = "AtomApplication";
|
|
||||||
NSQuitAlwaysKeepsWindows = false;
|
|
||||||
NSRequiresAquaSystemAppearance = false;
|
|
||||||
NSSupportsAutomaticGraphicsSwitching = true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
in
|
|
||||||
buildNpmPackage {
|
buildNpmPackage {
|
||||||
pname = "paseo-desktop";
|
pname = "paseo-desktop";
|
||||||
inherit version;
|
version = (builtins.fromJSON (builtins.readFile ../package.json)).version;
|
||||||
|
|
||||||
src = lib.cleanSourceWith {
|
src = lib.cleanSourceWith {
|
||||||
src = ./..;
|
src = ./..;
|
||||||
filter =
|
filter = path: type: let
|
||||||
path: type:
|
baseName = builtins.baseNameOf path;
|
||||||
let
|
relPath = lib.removePrefix (toString ./..) path;
|
||||||
baseName = builtins.baseNameOf path;
|
in
|
||||||
relPath = lib.removePrefix (toString ./..) path;
|
|
||||||
in
|
|
||||||
# Exclude mobile-only platform code (we only need the web/electron build)
|
# Exclude mobile-only platform code (we only need the web/electron build)
|
||||||
!(lib.hasPrefix "/packages/app/android" relPath)
|
!(lib.hasPrefix "/packages/app/android" relPath)
|
||||||
&& !(lib.hasPrefix "/packages/app/ios" relPath)
|
&& !(lib.hasPrefix "/packages/app/ios" relPath)
|
||||||
@@ -102,15 +61,15 @@ buildNpmPackage {
|
|||||||
|
|
||||||
# Prevent onnxruntime-node's install script from running during automatic
|
# Prevent onnxruntime-node's install script from running during automatic
|
||||||
# npm rebuild. We manually rebuild only node-pty in buildPhase.
|
# npm rebuild. We manually rebuild only node-pty in buildPhase.
|
||||||
npmRebuildFlags = [ "--ignore-scripts" ];
|
npmRebuildFlags = ["--ignore-scripts"];
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
[
|
[
|
||||||
python3 # for node-gyp (node-pty)
|
python3 # for node-gyp (node-pty)
|
||||||
makeWrapper
|
|
||||||
]
|
]
|
||||||
++ lib.optionals stdenv.hostPlatform.isLinux [
|
++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||||
autoPatchelfHook
|
autoPatchelfHook
|
||||||
|
makeWrapper
|
||||||
copyDesktopItems
|
copyDesktopItems
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -143,56 +102,75 @@ buildNpmPackage {
|
|||||||
# Expo web export for the Electron renderer
|
# Expo web export for the Electron renderer
|
||||||
( cd packages/app && PASEO_WEB_PLATFORM=electron npx expo export --platform web )
|
( cd packages/app && PASEO_WEB_PLATFORM=electron npx expo export --platform web )
|
||||||
|
|
||||||
# Desktop main process (tsc only — NOT electron-builder)
|
# Desktop main process
|
||||||
npm run build:main --workspace=@getpaseo/desktop
|
npm run build:main --workspace=@getpaseo/desktop
|
||||||
|
|
||||||
|
${lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||||
|
# Let electron-builder create the native bundle layout (including helper
|
||||||
|
# app names and bundle identifiers), but source Electron from nixpkgs
|
||||||
|
# instead of downloading a release at build time.
|
||||||
|
(
|
||||||
|
cd packages/desktop
|
||||||
|
CSC_IDENTITY_AUTO_DISCOVERY=false \
|
||||||
|
../../node_modules/.bin/electron-builder \
|
||||||
|
--config electron-builder.yml \
|
||||||
|
--dir \
|
||||||
|
--mac \
|
||||||
|
--publish never \
|
||||||
|
--config.electronDist=${electron}/Applications \
|
||||||
|
--config.mac.notarize=false
|
||||||
|
)
|
||||||
|
''}
|
||||||
|
|
||||||
runHook postBuild
|
runHook postBuild
|
||||||
'';
|
'';
|
||||||
|
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
runHook preInstall
|
runHook preInstall
|
||||||
|
|
||||||
mkdir -p $out/share/paseo-desktop $out/bin
|
mkdir -p $out/bin
|
||||||
|
|
||||||
# Materialize only the desktop and daemon runtime graphs. Copying the
|
|
||||||
# complete monorepo used to ship every build-time dependency (including
|
|
||||||
# Electron, Expo tooling, and cross-platform builder binaries), making the
|
|
||||||
# desktop output larger than 2 GiB.
|
|
||||||
PASEO_TRACE_DESKTOP=1 node scripts/trace-daemon.mjs > desktop-files.txt
|
|
||||||
|
|
||||||
while IFS= read -r path; do
|
|
||||||
[ -z "$path" ] && continue
|
|
||||||
mkdir -p "$out/share/paseo-desktop/$(dirname "$path")"
|
|
||||||
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/
|
|
||||||
mkdir -p $out/share/paseo-desktop/packages/app
|
|
||||||
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
|
|
||||||
if [ -d skills ]; then
|
|
||||||
cp -a skills $out/share/paseo-desktop/
|
|
||||||
fi
|
|
||||||
|
|
||||||
${lib.optionalString stdenv.hostPlatform.isLinux ''
|
${lib.optionalString stdenv.hostPlatform.isLinux ''
|
||||||
|
mkdir -p $out/share/paseo-desktop
|
||||||
|
|
||||||
|
# Materialize only the desktop and daemon runtime graphs. Copying the
|
||||||
|
# complete monorepo used to ship every build-time dependency (including
|
||||||
|
# Electron, Expo tooling, and cross-platform builder binaries), making the
|
||||||
|
# desktop output larger than 2 GiB.
|
||||||
|
PASEO_TRACE_DESKTOP=1 node scripts/trace-daemon.mjs > desktop-files.txt
|
||||||
|
|
||||||
|
while IFS= read -r path; do
|
||||||
|
[ -z "$path" ] && continue
|
||||||
|
mkdir -p "$out/share/paseo-desktop/$(dirname "$path")"
|
||||||
|
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/
|
||||||
|
mkdir -p $out/share/paseo-desktop/packages/app
|
||||||
|
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
|
||||||
|
if [ -d skills ]; then
|
||||||
|
cp -a skills $out/share/paseo-desktop/
|
||||||
|
fi
|
||||||
|
|
||||||
# Hicolor icon for desktop environments
|
# Hicolor icon for desktop environments
|
||||||
install -Dm644 packages/desktop/assets/icon.png \
|
install -Dm644 packages/desktop/assets/icon.png \
|
||||||
$out/share/icons/hicolor/512x512/apps/paseo-desktop.png
|
$out/share/icons/hicolor/512x512/apps/paseo-desktop.png
|
||||||
@@ -207,30 +185,13 @@ buildNpmPackage {
|
|||||||
''}
|
''}
|
||||||
|
|
||||||
${lib.optionalString stdenv.hostPlatform.isDarwin ''
|
${lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||||
app="$out/Applications/Paseo.app"
|
app="$(find packages/desktop/release -maxdepth 3 -type d -name Paseo.app -print -quit)"
|
||||||
mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources"
|
if [ -z "$app" ]; then
|
||||||
|
echo "electron-builder did not produce Paseo.app" >&2
|
||||||
# Reuse nixpkgs' Electron framework through store symlinks so the Paseo
|
exit 1
|
||||||
# output stays small while still presenting a normal application bundle
|
fi
|
||||||
# to LaunchServices.
|
mkdir -p "$out/Applications"
|
||||||
ln -s ${electron}/Applications/Electron.app/Contents/Frameworks \
|
cp -R "$app" "$out/Applications/Paseo.app"
|
||||||
"$app/Contents/Frameworks"
|
|
||||||
ln -s ${electron}/Applications/Electron.app/Contents/MacOS/Electron \
|
|
||||||
"$app/Contents/MacOS/Electron"
|
|
||||||
for resource in ${electron}/Applications/Electron.app/Contents/Resources/*; do
|
|
||||||
ln -s "$resource" "$app/Contents/Resources/$(basename "$resource")"
|
|
||||||
done
|
|
||||||
|
|
||||||
cp ${darwinInfoPlist} "$app/Contents/Info.plist"
|
|
||||||
cp ${electron}/Applications/Electron.app/Contents/PkgInfo "$app/Contents/PkgInfo"
|
|
||||||
cp packages/desktop/assets/icon.icns "$app/Contents/Resources/Paseo.icns"
|
|
||||||
|
|
||||||
# Keep the same unpackaged runtime layout as the Linux Nix package. The
|
|
||||||
# outer .app supplies native macOS identity, icon, and URL handling while
|
|
||||||
# the wrapper points Electron at the immutable built main process.
|
|
||||||
makeWrapper "$app/Contents/MacOS/Electron" "$app/Contents/MacOS/Paseo" \
|
|
||||||
--add-flags "$out/share/paseo-desktop/packages/desktop/dist/main.js" \
|
|
||||||
--set EXPO_DEV_URL "paseo://app/"
|
|
||||||
ln -s ../Applications/Paseo.app/Contents/MacOS/Paseo "$out/bin/paseo-desktop"
|
ln -s ../Applications/Paseo.app/Contents/MacOS/Paseo "$out/bin/paseo-desktop"
|
||||||
''}
|
''}
|
||||||
|
|
||||||
@@ -245,7 +206,7 @@ buildNpmPackage {
|
|||||||
comment = "Self-hosted daemon for AI coding agents";
|
comment = "Self-hosted daemon for AI coding agents";
|
||||||
exec = "paseo-desktop";
|
exec = "paseo-desktop";
|
||||||
icon = "paseo-desktop";
|
icon = "paseo-desktop";
|
||||||
categories = [ "Development" ];
|
categories = ["Development"];
|
||||||
startupWMClass = "Paseo";
|
startupWMClass = "Paseo";
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user