From 4d27f4cc027509b9a6555218715ea3544076a4db Mon Sep 17 00:00:00 2001 From: servius Date: Sun, 14 Jun 2026 02:25:03 +0530 Subject: [PATCH] Add Goose desktop package --- home/programs/goose.nix | 10 ++--- overlays/ai.nix | 90 ++++++++++++++++++++++++++++++++++------- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/home/programs/goose.nix b/home/programs/goose.nix index 012cd25..d77b47b 100644 --- a/home/programs/goose.nix +++ b/home/programs/goose.nix @@ -7,14 +7,14 @@ }: lib.mkMerge [ { - # goose-ai = the `goose` CLI; goosed-bin = the `goosed` agent server (mobile - # tunnel API), prebuilt-extracted and x86_64-linux only. + # goose-ai = the `goose` CLI; goose-desktop = the Electron desktop app plus + # `goosed` agent server, prebuilt and x86_64-linux only. home.packages = [pkgs.goose-ai] - ++ lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-linux") [pkgs.goosed-bin]; + ++ lib.optionals (pkgs.stdenv.hostPlatform.system == "x86_64-linux") [pkgs.goose-desktop]; } - # Mobile-tunnel server + secret, ryu only (goosed-bin is x86_64-linux and the + # Mobile-tunnel server + secret, ryu only (goose-desktop is x86_64-linux and the # tunnel is paired from the desktop). The token authenticates goosed's local # API; the per-pairing tunnel secret is generated by goosed itself. (lib.mkIf (device.is "ryu") { @@ -41,7 +41,7 @@ lib.mkMerge [ "GOOSE_TUNNEL=none" ]; EnvironmentFile = config.sops.templates."goose.env".path; - ExecStart = "${pkgs.goosed-bin}/bin/goosed agent"; + ExecStart = "${pkgs.goose-desktop}/bin/goosed agent"; Restart = "on-failure"; RestartSec = 5; }; diff --git a/overlays/ai.nix b/overlays/ai.nix index 4ecdf69..f2bd04b 100644 --- a/overlays/ai.nix +++ b/overlays/ai.nix @@ -23,6 +23,13 @@ }; source = sources.${stdenv.hostPlatform.system} or (throw "goose-ai is unsupported on ${stdenv.hostPlatform.system}"); + + gooseDesktopRuntimeDependencies = with prev; [ + libGL + libgbm + libxkbcommon + vulkan-loader + ]; in { goose-ai = stdenv.mkDerivation { pname = "goose-ai"; @@ -59,14 +66,11 @@ in { }; }; - # `goosed` (the agent server) is NOT shipped in the CLI tarball above — it only - # exists inside the Desktop app bundle. It provides the mobile tunnel API - # (POST /tunnel/start etc.) used to pair the iOS app from the CLI. Extract the - # prebuilt binary from the Linux .deb rather than compiling goose-server from - # source (which pulls in V8 via the code-mode feature). x86_64-linux only — - # upstream publishes no arm/darwin desktop .deb. - goosed-bin = stdenv.mkDerivation { - pname = "goosed-bin"; + # The desktop bundle also contains `goosed`, the agent server used by the + # mobile tunnel API. Keep the CLI package above as `goose`; this package's app + # launcher is named `goose-desktop` to avoid a Home Manager collision. + goose-desktop = stdenv.mkDerivation { + pname = "goose-desktop"; inherit version; src = prev.fetchurl { @@ -77,34 +81,90 @@ in { nativeBuildInputs = [ prev.dpkg prev.autoPatchelfHook + prev.makeWrapper ]; - buildInputs = [ + buildInputs = with prev; [ + alsa-lib + at-spi2-atk + at-spi2-core + atk + cairo + cups + dbus + expat + gdk-pixbuf + glib + gtk3 + libdrm + libgbm + libGL + libnotify + libsecret + libuuid + libx11 + libxcb + libxcomposite + libxdamage + libxext + libxfixes + libxkbfile + libxkbcommon + libxrandr + libxscrnsaver + libxshmfence + mesa + nspr + nss + pango stdenv.cc.cc.lib + systemd ]; + runtimeDependencies = gooseDesktopRuntimeDependencies; + dontConfigure = true; dontBuild = true; - # Stream the data tarball and extract only goosed — a full `dpkg-deb -x` - # fails in the sandbox trying to set the setuid bit on chrome-sandbox. + # `dpkg-deb -x` tries to preserve the setuid bit on chrome-sandbox. Extract + # via tar instead and run Electron with --no-sandbox from the wrapper. unpackPhase = '' runHook preUnpack - dpkg-deb --fsys-tarfile $src | tar -x ./usr/lib/goose/resources/bin/goosed + dpkg-deb --fsys-tarfile $src | tar -x --no-same-owner --no-same-permissions runHook postUnpack ''; installPhase = '' runHook preInstall - install -Dm755 usr/lib/goose/resources/bin/goosed $out/bin/goosed + + mkdir -p $out/bin $out/lib $out/share + cp -r usr/lib/goose $out/lib/ + cp -r usr/share/doc $out/share/ + cp -r usr/share/pixmaps $out/share/ + + install -Dm644 usr/share/applications/goose.desktop \ + $out/share/applications/goose.desktop + substituteInPlace $out/share/applications/goose.desktop \ + --replace-fail "Exec=/usr/lib/goose/Goose %U" "Exec=$out/bin/goose-desktop %U" \ + --replace-fail "Icon=/usr/share/pixmaps/goose.png" "Icon=$out/share/pixmaps/goose.png" + + makeWrapper $out/lib/goose/Goose $out/bin/goose-desktop \ + --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath gooseDesktopRuntimeDependencies}" \ + --prefix PATH : "$out/lib/goose/resources/bin:${lib.makeBinPath [prev.glib prev.xdg-utils]}" \ + --add-flags "--no-sandbox" + + makeWrapper $out/lib/goose/resources/bin/goosed $out/bin/goosed \ + --prefix PATH : "$out/lib/goose/resources/bin:${lib.makeBinPath [prev.glib prev.xdg-utils]}" + runHook postInstall ''; meta = { - description = "goose agent server (goosed), extracted from the prebuilt Desktop bundle"; + description = "Open source, extensible AI agent desktop app"; homepage = "https://github.com/aaif-goose/goose"; license = lib.licenses.asl20; - mainProgram = "goosed"; + sourceProvenance = with lib.sourceTypes; [binaryNativeCode]; + mainProgram = "goose-desktop"; platforms = ["x86_64-linux"]; }; }; -- 2.51.2