Some checks failed
CI / check (push) Has been cancelled
- aionui 2.1.4 -> 2.1.50 - desloppify 0.9.15 -> 1.0 - ds4 -> 2026-08-05 (b030961) - freebuff 0.0.85 -> 0.0.142 (binary moved to GitHub releases) - graphify 0.7.10 -> 0.9.35 (license Apache-2.0, fix sed patterns for versioned deps) - hipengine 0.2.2 -> 0.3.0 (console script renamed to hipengine) - kubernetes-mcp-server 0.0.62 -> 0.0.66 (requires go >= 1.26.3) - mcp-gateway 2.11.0 -> 3.4.0 (requires rustc >= 1.95) - omniroute 3.8.28 -> 3.8.49 - radar 1.6.1 -> 1.9.1 (drop obsolete lockfile sed patch) - relay-free-llm -> 96e6c48, cerebras-cloud-sdk 1.67.0 -> 1.91.0 - stakpak 0.3.86 -> 0.3.88 Add nixpkgs-latest input for toolchains newer than the pinned nixpkgs.
231 lines
7.0 KiB
Nix
231 lines
7.0 KiB
Nix
{
|
||
lib,
|
||
stdenv,
|
||
fetchFromGitHub,
|
||
bun,
|
||
nodejs,
|
||
node-gyp,
|
||
electron,
|
||
autoPatchelfHook,
|
||
makeWrapper,
|
||
copyDesktopItems,
|
||
imagemagick,
|
||
python3,
|
||
cacert,
|
||
}:
|
||
|
||
let
|
||
version = "2.1.50";
|
||
|
||
src = fetchFromGitHub {
|
||
owner = "iOfficeAI";
|
||
repo = "AionUi";
|
||
rev = "v${version}";
|
||
hash = "sha256-NsKygGMRN5pQXyKaehVW/sC2tyd4KmrYmiQrr5ZGeNY=";
|
||
};
|
||
|
||
# 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-EeDapBXeiU/70N92ka1dmrKUMEDN65FON8VPVPsBfro=";
|
||
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-L2UV+OsHfoQTsc1s+tBrJZtnoiCcB2mlnsAHbplTggc=";
|
||
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;
|
||
};
|
||
}
|