Files
alex e2f24b0876 chore(packages): bump pins to current upstream releases
- awg-tool 0.4.0 -> 0.5.0
- awgen 0.1 -> 0.2
- codeaf 0.7.1 -> 0.8.2
- ds4 -> ee7e840 (2026-10-21)
- freebuff 0.2.19 -> 0.2.34
- graphify 0.9.77 -> 0.9.95 (add pyyaml dependency)
- hipengine 0.6.1 -> 0.8.3
- kubernetes-mcp-server 0.0.67 -> 0.0.69 (build with go_1_27)
- kyojin 1.3 -> 1.7.1 (drop obsolete setup.py/pyproject patches, ship
  gr_mix_hip from the package, add ninja runtime dependency)
- marmel -> de3e99c (2026-10-23)
- omniroute 3.8.50 -> 3.8.52
- open-code-review 1.12.12 -> 1.13.3 (build with go_1_27)
- pilotdeck 2026.10.17 -> 2026.10.20
- radar 1.16.2 -> 1.18.0
- traycer 1.4.2 -> 1.5.1

Verified: nix build passes for every bumped package; kyojin.tests.jit
compiles all five JIT kernels.

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
2026-10-24 14:09:34 +03:00

466 lines
15 KiB
Nix

{
lib,
stdenv,
fetchFromGitHub,
fetchurl,
fetchPnpmDeps,
pnpmConfigHook,
nodejs_22,
nodejs-slim_22,
pnpm_10,
python3,
sqlite,
makeWrapper,
copyDesktopItems,
makeDesktopItem,
ripgrep,
git,
curl,
procps,
bashInteractive,
coreutils,
findutils,
gnugrep,
gnused,
electron_42,
libx11,
libxi,
libxtst,
libxext,
libxkbcommon,
wayland,
at-spi2-core,
}:
let
version = "2026.10.20";
# apps/desktop/package.json carries the Electron application version used
# by the UI build marker and the desktop package manifest.
desktopVersion = "0.1.0";
uiVersion = "0.1.0";
# Keep the source, LFS asset, pnpm dependency, and Cua driver hashes in
# sync with the upstream release when updating the version.
pnpm = pnpm_10.override { nodejs-slim = nodejs-slim_22; };
# Git LFS objects used by the web UI and the memory-core package. The
# upstream tarball contains pointer files, so fetch these paths through
# git-lfs and overlay them on the source tree.
lfsAssets = fetchFromGitHub {
owner = "OpenBMB";
repo = "PilotDeck";
tag = "v${version}";
fetchLFS = true;
sparseCheckout = [
"ui/public"
"src/context/memory/edgeclaw-memory-core/ui-source/assets"
];
hash = "sha256-R0bMxC6B2XqJMzuBnHmlNPX65tIwxL5FUc6Vv5M3O7w=";
};
cuaDriver =
{
x86_64-linux = fetchurl {
url = "https://github.com/trycua/cua/releases/download/cua-driver-rs-v0.34.1/cua-driver-rs-0.34.1-linux-x86_64-binary.tar.gz";
hash = "sha256-pB/ivcvupFAdxZTAdPFrCXVyjgzHsIuQrOqFZNSPr+4=";
};
aarch64-linux = fetchurl {
url = "https://github.com/trycua/cua/releases/download/cua-driver-rs-v0.34.1/cua-driver-rs-0.34.1-linux-arm64-binary.tar.gz";
hash = "sha256-HIOdNUAbveog8+HPUKzpJu8Xvm8yzqfoIbArJjxJM9w=";
};
}
.${stdenv.hostPlatform.system}
or (throw "pilotdeck: unsupported system ${stdenv.hostPlatform.system}");
# The desktop runtime installs its production dependencies from the
# standalone lockfile in apps/desktop/runtime. That lockfile refers to the
# memory-core package as `file:../../../src/...`, which resolves three
# directories above the runtime package, so the fetcher needs a source tree
# with exactly that layout.
runtimeManifestSrc = stdenv.mkDerivation {
name = "pilotdeck-desktop-runtime-manifest";
src = fetchFromGitHub {
owner = "OpenBMB";
repo = "PilotDeck";
tag = "v${version}";
hash = "sha256-y6U0aMiVT7Nt8g0+x5TUZ9gf/WbEDB5n0JM/DjUMS0w=";
};
dontConfigure = true;
dontBuild = true;
installPhase = ''
mkdir -p "$out/apps/desktop/runtime" "$out/src/context/memory/edgeclaw-memory-core"
cp apps/desktop/runtime/package.json "$out/apps/desktop/runtime/"
cp apps/desktop/runtime/pnpm-lock.yaml "$out/apps/desktop/runtime/"
cp src/context/memory/edgeclaw-memory-core/package.json \
"$out/src/context/memory/edgeclaw-memory-core/"
'';
};
in
stdenv.mkDerivation (finalAttrs: {
pname = "pilotdeck";
inherit version;
src = fetchFromGitHub {
owner = "OpenBMB";
repo = "PilotDeck";
tag = "v${version}";
hash = "sha256-y6U0aMiVT7Nt8g0+x5TUZ9gf/WbEDB5n0JM/DjUMS0w=";
};
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs)
pname
version
src
;
inherit pnpm;
pnpmWorkspaces = [
"pilotdeck"
"pilotdeck-ui"
"pilotdeck-desktop"
];
fetcherVersion = 4;
hash = "sha256-AvKOMzkYQvdjWO4FNkIwScdws4HxNhBXTuMNy9QIBbM=";
};
runtimePnpmDeps = fetchPnpmDeps {
pname = "${finalAttrs.pname}-desktop-runtime";
inherit version;
src = runtimeManifestSrc;
sourceRoot = "${runtimeManifestSrc.name}/apps/desktop/runtime";
inherit pnpm;
fetcherVersion = 4;
hash = "sha256-1SBgYsX1nZiuWYy8UG1vTNst9KrJOAHsrriOfJZLlhE=";
};
pnpmWorkspaces = [
"pilotdeck"
"pilotdeck-ui"
"pilotdeck-desktop"
];
nativeBuildInputs = [
nodejs_22
pnpm
pnpmConfigHook
python3
sqlite
makeWrapper
copyDesktopItems
];
env = {
# node-gyp must use the headers of the Node.js runtime that will execute
# the native addons, rather than downloading headers from nodejs.org.
npm_config_nodedir = nodejs_22;
npm_config_offline = "true";
pnpm_config_offline = "true";
};
postUnpack = ''
cp -r ${lfsAssets}/ui/public/. source/ui/public/
cp -r ${lfsAssets}/src/context/memory/edgeclaw-memory-core/ui-source/assets/. \
source/src/context/memory/edgeclaw-memory-core/ui-source/assets/
'';
preConfigure = ''
export HOME=$TMPDIR
'';
desktopItems = [
(makeDesktopItem {
name = "pilotdeck";
desktopName = "PilotDeck";
genericName = "AI agent desktop";
exec = "pilotdeck %U";
icon = "pilotdeck";
comment = "Task-oriented AI agent desktop application";
categories = [
"Utility"
"Development"
];
startupWMClass = "pilotdeck-desktop";
terminal = false;
})
];
buildPhase = ''
runHook preBuild
# pnpmConfigHook installs dependencies with --ignore-scripts. Run the
# allowed lifecycle scripts now. better-sqlite3 and node-pty fall back to
# a source build when their prebuilt download is unavailable, while sharp
# uses its prebuilt @img/sharp-* optional dependency.
pnpm rebuild
pnpm --filter pilotdeck-ui rebuild
# The build script verifies and stages the pinned Cua computer-use driver.
# Point it at the Nix store instead of letting it download the archive.
export PILOTDECK_CUA_ARCHIVE=${cuaDriver}
npm run build
# The UI build gets the desktop marker the upstream desktop packaging
# sets (apps/desktop/scripts/build-runtime.mjs).
VITE_PILOTDECK_DESKTOP_BUILD=${desktopVersion} pnpm --filter pilotdeck-ui run build
# Compile the Electron main process.
pnpm --filter pilotdeck-desktop run compile
# Desktop runtime staging (apps/desktop/scripts/build-runtime.mjs). The
# runtime installs its production dependencies from their own lockfile
# in a hoisted layout and must never contain the TypeScript sources or
# tsx.
runtimeStore=$(mktemp -d)
tar --zstd -xf ${finalAttrs.runtimePnpmDeps}/pnpm-store.tar.zst -C "$runtimeStore"
chmod -R u+w "$runtimeStore"
if [ -f "$runtimeStore/v11/index.db.sql" ]; then
sqlite3 "$runtimeStore/v11/index.db" < "$runtimeStore/v11/index.db.sql"
rm -f "$runtimeStore/v11/index.db.sql"
fi
mkdir -p apps/desktop/.runtime-install
cp apps/desktop/runtime/package.json apps/desktop/.runtime-install/
cp apps/desktop/runtime/pnpm-lock.yaml apps/desktop/.runtime-install/
pushd apps/desktop/.runtime-install
PLAYWRIGHT_BROWSERS_PATH=0 pnpm \
--config.store-dir="$runtimeStore" \
install \
--prod \
--ignore-workspace \
--config.node-linker=hoisted \
--frozen-lockfile \
--ignore-scripts
popd
# The build sandbox has no /usr/bin/env, so rewrite the interpreter
# lines the way pnpmConfigHook does for the workspace install.
patchShebangs apps/desktop/.runtime-install/node_modules/{*,.*}
pushd apps/desktop/.runtime-install
# Linux ships no prebuilds for these native addons; compile them against
# the bundled Node.js headers.
pnpm \
--config.store-dir="$runtimeStore" \
rebuild \
better-sqlite3 \
bcrypt \
node-pty \
--ignore-workspace \
--config.node-linker=hoisted
popd
# pnpm caches file: dependency packs in its store, which would keep the
# pre-build content without lib/. Replace the cached copy with the
# freshly built package.
rm -rf apps/desktop/.runtime-install/node_modules/edgeclaw-memory-core
cp -r src/context/memory/edgeclaw-memory-core \
apps/desktop/.runtime-install/node_modules/edgeclaw-memory-core
# Assemble the runtime tree exactly like upstream build-runtime.mjs:
# compiled gateway, skills, UI server with source imports rewritten to
# the compiled tree, UI assets, the pinned Cua driver, and the
# computer-use scripts. The memory-core source snapshot is replaced by
# the node_modules copy, matching the upstream staging layout.
runtimeInstall=$PWD/apps/desktop/.runtime-install
cp -r dist $runtimeInstall/dist
cp -r skills $runtimeInstall/skills
mkdir -p $runtimeInstall/src/context/memory
cp -r src/context/memory/edgeclaw-memory-core $runtimeInstall/src/context/memory/
mkdir -p $runtimeInstall/ui $runtimeInstall/resources $runtimeInstall/scripts
cp -r ui/server $runtimeInstall/ui/server
cp -r ui/shared $runtimeInstall/ui/shared
cp -r ui/public $runtimeInstall/ui/public
cp -r ui/dist $runtimeInstall/ui/dist
cp -r resources/cua-driver $runtimeInstall/resources/cua-driver
cp -r scripts/computer-use $runtimeInstall/scripts/computer-use
cp -r scripts/lib $runtimeInstall/scripts/lib
install scripts/check-node-runtime.mjs $runtimeInstall/scripts/
install scripts/install-asr.mjs $runtimeInstall/scripts/
install scripts/prepare-computer-use.mjs $runtimeInstall/scripts/
# The UI server runs as plain JavaScript, so rewrite its source imports
# to the compiled gateway (rewriteUiServerSourceImports).
find $runtimeInstall/ui/server -type f -name '*.js' -exec sed -i \
-e 's|\.\./\.\./src/|../../dist/src/|g' \
-e 's|\.\./\.\./\.\./src/|../../../dist/src/|g' \
{} \;
cat > $runtimeInstall/ui/package.json <<'EOF'
{
"name": "pilotdeck-ui-runtime",
"version": "${uiVersion}",
"private": true,
"type": "module"
}
EOF
rm -rf $runtimeInstall/src
# Verify the staged runtime the way upstream build-runtime does.
export NODE_PATH=$runtimeInstall/node_modules
LD_LIBRARY_PATH=${lib.makeLibraryPath [ stdenv.cc.cc.lib ]} \
node -e 'const Database = require("better-sqlite3"); new Database(":memory:");'
node apps/desktop/scripts/verify-runtime-pty.cjs "$runtimeInstall"
# The CLI entry starts a proxy server on import (top-level await), so
# each probe must exit explicitly like the upstream verification does.
PILOTDECK_SKIP_CLI_MAIN=1 node --input-type=module \
-e "await import('file://$runtimeInstall/dist/src/cli/pilotdeck.js'); process.exit(0);"
node --input-type=module \
-e "await import('file://$runtimeInstall/ui/server/services/spreadsheetPreview.js'); process.exit(0);"
node --input-type=module \
-e "await import('file://$runtimeInstall/ui/server/services/standaloneComputerUse.js'); process.exit(0);"
unset NODE_PATH
runHook postBuild
'';
installPhase = ''
runHook preInstall
appRoot=$out/share/pilotdeck
# Staged web runtime: compiled gateway, UI server with source imports
# rewritten to the compiled tree, hoisted production node_modules, the
# pinned Cua driver, and the computer-use scripts.
mkdir -p $out/share $appRoot
mv apps/desktop/.runtime-install $appRoot/runtime
rm -f $appRoot/runtime/pnpm-lock.yaml
# Electron main process: the app directory the Electron launcher loads,
# with PILOTDECK_DESKTOP_RUNTIME_ROOT pointing at the staged runtime.
mkdir -p $appRoot/dist $appRoot/resources
cp -r apps/desktop/dist/. $appRoot/dist/
cp apps/desktop/package.json $appRoot/package.json
cp -r apps/desktop/resources/icons $appRoot/resources/icons
cp apps/desktop/resources/build-metadata.json $appRoot/resources/
# electron-updater is imported by the Electron main process, so the app
# needs it with its full dependency closure. pnpm keeps each package's
# deps as sibling symlinks around it; expand every reachable virtual
# store scope into a self-contained, hoisted node_modules directory
# while preserving the exact dependency versions pnpm resolved.
appNodeModules=$appRoot/node_modules
mkdir -p "$appNodeModules"
pendingScopes=(
"$(dirname "$(readlink -f apps/desktop/node_modules/electron-updater)")"
)
expandedScopes=" $pendingScopes "
while [ ''${#pendingScopes[@]} -gt 0 ]; do
scope=''${pendingScopes[0]}
pendingScopes=("''${pendingScopes[@]:1}")
# Copy every package in the scope into the app node_modules. Each
# dependency symlink points at a sibling scope in pnpm's virtual
# store; dereference it and queue that scope for expansion.
for entry in "$scope"/* "$scope"/.[!.]*; do
name=$(basename "$entry")
case "$name" in .bin|.pnpm) continue ;; esac
[ -e "$appNodeModules/$name" ] && continue
if [ -h "$entry" ]; then
tgt=$(readlink -f "$entry")
cp -Lr "$tgt" "$appNodeModules/$name"
realScope=$(dirname "$tgt")
case "$expandedScopes" in
*" $realScope "*) ;;
*)
expandedScopes="$expandedScopes$realScope "
pendingScopes+=("$realScope")
;;
esac
else
cp -Lr "$entry" "$appNodeModules/$name"
fi
done 2>/dev/null
done
unset pendingScopes expandedScopes scope entry tgt realScope name
# The dev launcher resolves the Cua driver at <three levels above the
# app directory>/resources/cua-driver.
mkdir -p $out/resources
ln -s $appRoot/runtime/resources/cua-driver $out/resources/cua-driver
# Application icon.
mkdir -p $out/share/icons/hicolor/256x256/apps
install -m 444 apps/desktop/resources/icons/icon.png \
$out/share/icons/hicolor/256x256/apps/pilotdeck.png
# Desktop client: launch Electron with the app directory and the
# packaged-style runtime root. Chromium's setuid sandbox is unavailable
# inside the Nix store, so disable it the way other store-based
# launchers do.
makeWrapper ${electron_42}/libexec/electron/electron $out/bin/pilotdeck \
--add-flags "$appRoot" \
--add-flags "--no-sandbox" \
--add-flags "--ozone-platform-hint=auto" \
--set PILOTDECK_DESKTOP_RUNTIME_ROOT $appRoot/runtime \
--set PILOTDECK_DESKTOP_NODE ${nodejs_22}/bin/node \
--prefix PATH : ${
lib.makeBinPath [
nodejs_22
ripgrep
git
curl
procps
bashInteractive
coreutils
findutils
gnugrep
gnused
]
} \
--prefix LD_LIBRARY_PATH : ${
lib.makeLibraryPath [
libx11
libxi
libxtst
libxext
libxkbcommon
wayland
at-spi2-core
stdenv.cc.cc.lib
]
}
# Headless alternative: the same staged runtime as the plain web server.
makeWrapper ${lib.getExe nodejs_22} $out/bin/pilotdeck-server \
--add-flags "$appRoot/runtime/ui/server/webRuntimeSupervisor.js start-built" \
--prefix PATH : ${
lib.makeBinPath [
nodejs_22
ripgrep
git
curl
procps
bashInteractive
coreutils
findutils
gnugrep
gnused
]
} \
--prefix LD_LIBRARY_PATH : ${
lib.makeLibraryPath [
libx11
libxi
libxtst
libxext
libxkbcommon
wayland
at-spi2-core
stdenv.cc.cc.lib
]
}
runHook postInstall
'';
passthru.category = "AI Agents";
meta = {
description = "PilotDeck Electron desktop application and headless web server, built from source";
homepage = "https://github.com/OpenBMB/PilotDeck";
license = lib.licenses.agpl3Only;
mainProgram = "pilotdeck";
platforms = [
"x86_64-linux"
"aarch64-linux"
];
};
})