diff --git a/README.md b/README.md index ec215f7..d855e13 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ A custom Nix overlay and flake providing additional packages not found in upstre | `radar` | Modern Kubernetes visibility — topology, event timeline, service traffic, resource browsing, Helm management, and GitOps support | Kubernetes | | `omniroute` | Unified AI router with 160+ providers, auto fallback, MCP/A2A, OpenAI-compatible APIs | AI LLM Gateway | | `open-code-review` | AI-powered code review CLI combining deterministic pipelines with an LLM agent for line-level review comments | AI Coding Agents | -| `pilotdeck` | Task-oriented AI Agent productivity platform with WorkSpace isolation, white-box memory, and smart routing | AI Agents | +| `pilotdeck` | Task-oriented AI Agent productivity platform (source-built web UI and gateway) with WorkSpace isolation, white-box memory, and smart routing | AI Agents | | `relay-free-llm` | RESTful API to route user prompts to various AI model providers with automatic failover and intent-based routing | AI LLM Gateway | | `stakpak` | DevOps AI agent that generates infrastructure code, debugs Kubernetes, configures CI/CD, and automates deployments | AI Agents | | `traycer` | Open-source AI orchestration app for agentic coding | AI Coding Agents | @@ -230,7 +230,7 @@ nix-overlay/ │ ├── mcp-gateway/ # MCP protocol gateway │ ├── omniroute/ # Unified AI router with 160+ providers │ ├── open-code-review/ # AI code review CLI (deterministic + LLM agent) -│ ├── pilotdeck/ # Task-oriented AI Agent productivity platform +│ ├── pilotdeck/ # Task-oriented AI Agent platform (source-built web UI) │ ├── radar/ # Kubernetes UI (topology, timeline, Helm, GitOps) │ ├── relay-free-llm/ # AI model provider routing gateway │ ├── skillsmcp/ # MCP server for Agent Skills diff --git a/packages/pilotdeck/package.nix b/packages/pilotdeck/package.nix index d5c60c2..dd5e9de 100644 --- a/packages/pilotdeck/package.nix +++ b/packages/pilotdeck/package.nix @@ -1,182 +1,213 @@ { lib, stdenv, + fetchFromGitHub, fetchurl, - dpkg, - autoPatchelfHook, + fetchPnpmDeps, + pnpmConfigHook, + nodejs_22, + nodejs-slim_22, + pnpm_10, + python3, makeWrapper, - alsa-lib, - at-spi2-atk, - cairo, - cups, - dbus, - expat, - gdk-pixbuf, - glib, - gtk3, - gtk4, - libdrm, - libgbm, - libGL, - libnotify, - libpulseaudio, - libsecret, + ripgrep, + git, + curl, + procps, + bashInteractive, + coreutils, + findutils, + gnugrep, + gnused, libx11, - libxcb, - libxcomposite, - libxdamage, + libxi, + libxtst, libxext, - libxfixes, libxkbcommon, - libxrandr, - libxshmfence, - nspr, - nss, - pango, - pciutils, - pipewire, - speechd-minimal, - systemd, - vulkan-loader, + wayland, + at-spi2-core, }: let version = "2026.10.17"; - # Release tags use dotted dates (v2026.10.17), but the Debian artifacts use - # the release date with a build suffix (2026.1017.0). - versionParts = lib.splitString "." version; - debVersion = "${lib.elemAt versionParts 0}.${lib.elemAt versionParts 1}${lib.elemAt versionParts 2}.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; }; - arch = + # 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 = "x64"; - aarch64-linux = "arm64"; + 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}"); - - hashes = { - # The release publishes one Debian package per architecture. nix-update - # refreshes only the host architecture's hash; update the other one by hand - # from release.json in the GitHub release. - x86_64-linux = "sha256-vBqewHabntIz1hKbf10q9hkWX22m0U2mqJMXvX7cJOc="; - aarch64-linux = "sha256-paEEmWYkITfYTa3AsYD0WfVqtzzQ1GMlt5yjp7oXROY="; - }; - - runtimeLibs = [ - alsa-lib - at-spi2-atk - cairo - cups - dbus - expat - gdk-pixbuf - glib - gtk3 - gtk4 - libdrm - libgbm - libGL - libnotify - libpulseaudio - libsecret - libx11 - libxcb - libxcomposite - libxdamage - libxext - libxfixes - libxkbcommon - libxrandr - libxshmfence - nspr - nss - pango - pciutils - pipewire - speechd-minimal - stdenv.cc.cc.lib - systemd - vulkan-loader - ]; in -stdenv.mkDerivation { +stdenv.mkDerivation (finalAttrs: { pname = "pilotdeck"; inherit version; - src = fetchurl { - url = "https://github.com/OpenBMB/PilotDeck/releases/download/v${version}/PilotDeck-${debVersion}-linux-${arch}.deb"; - hash = hashes.${stdenv.hostPlatform.system}; + src = fetchFromGitHub { + owner = "OpenBMB"; + repo = "PilotDeck"; + tag = "v${version}"; + hash = "sha256-VgsMoaaAtLIieBr4TchP61u5xV3PnVqjviak6DN7TPY="; }; + pnpmDeps = fetchPnpmDeps { + inherit (finalAttrs) + pname + version + src + ; + inherit pnpm; + pnpmWorkspaces = [ + "pilotdeck" + "pilotdeck-ui" + ]; + fetcherVersion = 4; + hash = "sha256-yhLx1PGSGoyds8lUe3cKpqMWgITwic5YTxugATARV7Y="; + }; + + pnpmWorkspaces = [ + "pilotdeck" + "pilotdeck-ui" + ]; + nativeBuildInputs = [ - dpkg - autoPatchelfHook + nodejs_22 + pnpm + pnpmConfigHook + python3 makeWrapper ]; - buildInputs = runtimeLibs; + 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"; + }; - # The Debian package contains the complete Electron application, including - # the bundled Node.js runtime and the built web UI. - unpackPhase = '' - runHook preUnpack - dpkg-deb --extract $src . - runHook postUnpack + 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/ ''; - dontBuild = true; - dontStrip = true; + preConfigure = '' + export HOME=$TMPDIR + ''; + + 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} + pnpm run build:web + + runHook postBuild + ''; installPhase = '' runHook preInstall - mkdir -p $out/opt - cp -a opt/PilotDeck $out/opt/PilotDeck + mkdir -p $out/lib/pilotdeck + cp -r \ + package.json \ + tsconfig.json \ + node_modules \ + dist \ + src \ + scripts \ + skills \ + resources \ + $out/lib/pilotdeck/ - mkdir -p $out/share/applications - substitute usr/share/applications/pilotdeck-desktop.desktop \ - $out/share/applications/pilotdeck.desktop \ - --replace-fail 'Exec=/opt/PilotDeck/pilotdeck-desktop %U' 'Exec=pilotdeck %U' \ - --replace-fail 'Icon=pilotdeck-desktop' 'Icon=pilotdeck' + mkdir -p $out/lib/pilotdeck/ui + cp -r \ + ui/package.json \ + ui/server \ + ui/dist \ + ui/public \ + ui/scripts \ + ui/shared \ + ui/vite.config.js \ + ui/node_modules \ + $out/lib/pilotdeck/ui/ - mkdir -p $out/share/icons/hicolor/256x256/apps - cp usr/share/icons/hicolor/256x256/apps/pilotdeck-desktop.png \ - $out/share/icons/hicolor/256x256/apps/pilotdeck.png - - makeWrapper $out/opt/PilotDeck/pilotdeck-desktop $out/bin/pilotdeck \ - --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath runtimeLibs}" + makeWrapper ${lib.getExe nodejs_22} $out/bin/pilotdeck \ + --add-flags "$out/lib/pilotdeck/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 ''; - # bcrypt ships glibc and musl prebuilds side by side; only the glibc one is - # used here, so the musl libc reference of the other prebuild stays unresolved. - autoPatchelfIgnoreMissingDeps = [ - "libc.musl-x86_64.so.1" - "libc.musl-aarch64.so.1" - ]; + passthru.category = "AI Agents"; - passthru = { - category = "AI Agents"; - updateScript = [ - "nix-update" - "--flake" - ".#pilotdeck" - ]; - }; - - meta = with lib; { - description = "Task-oriented AI Agent productivity platform"; + meta = { + description = "Task-oriented AI Agent productivity platform (source-built web UI and gateway)"; homepage = "https://github.com/OpenBMB/PilotDeck"; - changelog = "https://github.com/OpenBMB/PilotDeck/releases/tag/v${version}"; - license = licenses.agpl3Only; - sourceProvenance = with sourceTypes; [ binaryNativeCode ]; + license = lib.licenses.agpl3Only; mainProgram = "pilotdeck"; platforms = [ "x86_64-linux" "aarch64-linux" ]; }; -} +})