Files
millerson-overlay.nix/packages/aionui/package.nix
Alexander Miroshnichenko 7f0cec1a35
Some checks failed
CI / check (push) Has been cancelled
fix(aionui): Use production-only deps for runtime, hoist transitive deps
Replace full node_modules copy with production-only FOD (mirrors
the upstream Dockerfile pattern), reducing package output from
~6.9 GB to ~1.3 GB.

Hoist @sentry/node to top-level node_modules so Electron's
require() resolution can find it. Bun nests transitive deps
inside .bun/ but Electron resolves from the realpath, requiring
the dependency to be accessible from the walked-up directory
chain.
2026-05-27 14:35:57 +03:00

231 lines
7.0 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
lib,
stdenv,
fetchFromGitHub,
bun,
nodejs,
node-gyp,
electron,
autoPatchelfHook,
makeWrapper,
copyDesktopItems,
imagemagick,
python3,
cacert,
}:
let
version = "2.1.4";
src = fetchFromGitHub {
owner = "iOfficeAI";
repo = "AionUi";
rev = "v${version}";
hash = "sha256-A7dKGEuo5n+M7D9fJR3TN95q1P7En/ulsTO+ev6SAUY=";
};
# FOD 1: All dependencies (dev + prod) for the build phase.
bunBuildDeps = stdenv.mkDerivation {
name = "aionui-build-deps-${version}";
inherit src;
nativeBuildInputs = [
bun
cacert
];
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = "sha256-Fuj55vxDgpx5A4iwnU/5IZKPfaYMH3DeZ1yauuZHn8g=";
dontPatchShebangs = true;
dontFixup = true;
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
buildPhase = ''
export HOME=$TMPDIR
bun install --frozen-lockfile --ignore-scripts
'';
installPhase = ''
mkdir -p $out
cp -r node_modules $out/
cp -r packages $out/
cp tsconfig.json $out/
'';
};
# FOD 2: Production-only dependencies for the runtime output.
# Mirrors the Dockerfile's `bun install --production --ignore-scripts`.
bunProdDeps = stdenv.mkDerivation {
name = "aionui-prod-deps-${version}";
inherit src;
nativeBuildInputs = [
bun
cacert
];
outputHashAlgo = "sha256";
outputHashMode = "recursive";
outputHash = "sha256-eCQ9ObhttZ10CehRRvl4IaOKkdK9m1TQJuhLmhiMkBY=";
dontPatchShebangs = true;
dontFixup = true;
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
buildPhase = ''
export HOME=$TMPDIR
bun install --frozen-lockfile --production --ignore-scripts
'';
installPhase = ''
mkdir -p $out
cp -r node_modules $out/
'';
};
in
stdenv.mkDerivation rec {
pname = "aionui";
inherit version src;
nativeBuildInputs = [
bun
nodejs
node-gyp
autoPatchelfHook
makeWrapper
copyDesktopItems
imagemagick
python3
];
buildInputs = [
stdenv.cc.cc.lib
];
buildPhase = ''
runHook preBuild
export HOME=$TMPDIR
# Use the full dependency set for the build
ln -sf ${bunBuildDeps}/node_modules .
# Build better-sqlite3 native addon
echo "Building better-sqlite3 from source..."
BT3_SRC=$TMPDIR/bts3-src
BT3_OUT=$TMPDIR/bts3-out
mkdir -p "$BT3_SRC" "$BT3_OUT"
cp -rL node_modules/better-sqlite3/* "$BT3_SRC/"
chmod -R u+w "$BT3_SRC"
(
cd "$BT3_SRC"
export npm_config_nodedir=${nodejs}
node-gyp rebuild
mkdir -p "$BT3_OUT/build/Release"
cp build/Release/better_sqlite3.node "$BT3_OUT/build/Release/" 2>/dev/null || true
)
# electron-vite build
echo "Running electron-vite build..."
${nodejs}/bin/node node_modules/.bin/electron-vite build \
--config packages/desktop/electron.vite.config.ts
# Bundle MCP servers
echo "Building MCP servers..."
${nodejs}/bin/node scripts/build-mcp-servers.js
runHook postBuild
'';
installPhase = ''
runHook preInstall
mkdir -p $out/{bin,lib/aionui}
# Built output
cp -r out $out/lib/aionui/
cp -r public $out/lib/aionui/
cp package.json $out/lib/aionui/
# Production-only node_modules (mirrors Dockerfile)
cp -a ${bunProdDeps}/node_modules $out/lib/aionui/node_modules
chmod -R u+w $out/lib/aionui/node_modules
# Remove workspace symlink @aionui/web-host is bundled by
# electron-vite (excluded from externalizeDepsPlugin), so the
# symlink to packages/web-host is not needed at runtime.
rm -f $out/lib/aionui/node_modules/@aionui/web-host
# @sentry/electron requires @sentry/node at runtime, but bun
# nests it inside .bun/ rather than hoisting to top-level.
# Electron's require() walks up from the resolved realpath
# and needs it accessible either at top-level or via the
# symlink target's node_modules. We ensure top-level access.
if [ ! -e $out/lib/aionui/node_modules/@sentry/node ]; then
SRC=$(echo $out/lib/aionui/node_modules/.bun/@sentry+node@*/node_modules/@sentry/node)
if [ -d "$SRC" ]; then
ln -sf "$(realpath --relative-to=$out/lib/aionui/node_modules/@sentry "$SRC")" \
$out/lib/aionui/node_modules/@sentry/node
fi
fi
# Inject compiled better-sqlite3 .node into the runtime tree
if [ -f "$TMPDIR/bts3-out/build/Release/better_sqlite3.node" ]; then
rm -rf $out/lib/aionui/node_modules/better-sqlite3
cp -rL ${bunProdDeps}/node_modules/better-sqlite3 $out/lib/aionui/node_modules/better-sqlite3 2>/dev/null || true
chmod -R u+w $out/lib/aionui/node_modules/better-sqlite3
mkdir -p $out/lib/aionui/node_modules/better-sqlite3/build/Release
cp "$TMPDIR/bts3-out/build/Release/better_sqlite3.node" \
$out/lib/aionui/node_modules/better-sqlite3/build/Release/
fi
# Desktop entry
mkdir -p $out/share/applications
cat > $out/share/applications/aionui.desktop << EOF
[Desktop Entry]
Name=AionUi
Comment=Free, open-source Cowork app with AI Agents
Exec=$out/bin/aionui
Icon=aionui
Terminal=false
Type=Application
Categories=Office;Utility;
EOF
mkdir -p $out/share/icons/hicolor/256x256/apps
if [ -f resources/app.png ]; then
convert resources/app.png -resize 256x256 \
$out/share/icons/hicolor/256x256/apps/aionui.png
fi
# Launcher
makeWrapper ${electron}/bin/electron $out/bin/aionui \
--add-flags "$out/lib/aionui"
runHook postInstall
'';
dontStrip = true;
autoPatchelfIgnoreMissingDeps = true;
desktopItems = [ "aionui.desktop" ];
doCheck = false;
passthru = {
category = "AI Coding Agents";
updateScript = [
"nix-update"
"--flake"
".#aionui"
];
};
meta = with lib; {
description = "Free, open-source, Cowork app with AI Agents";
homepage = "https://github.com/iOfficeAI/AionUi";
changelog = "https://github.com/iOfficeAI/AionUi/releases/tag/v${version}";
license = licenses.asl20;
sourceProvenance = with sourceTypes; [ fromSource ];
mainProgram = "aionui";
platforms = platforms.linux;
};
}