From 7b9fc9c5b718e1752f44460557359f19266d0d24 Mon Sep 17 00:00:00 2001 From: Felix Rath Date: Sat, 30 May 2026 16:51:44 +0200 Subject: [PATCH] fix(nix): Add Linux-support for the tray manager in AppIndicator trays Assisted-by: gpt-5.5 --- CHANGELOG.md | 1 + docs/02-usage/060_dashboard.md | 4 +- flake.nix | 148 ++++++++++++++---- .../resources/serena_config.template.yml | 2 + 4 files changed, 119 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29f774dc..0ce28a00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Status of the `main` branch. Changes prior to the next official version change w - Decouple configuration computation from the agent's task queue by introducing events for agent config/status updates. This allows the dashboard to display the configuration while the project provided at startup is still initialising. #1064 - Fix empty executions queue displaying "Loading..." + - Tray manager: Add NixOS-support for AppIndicator-based trays (e.g., most Wayland-trays) to the package in flake.nix. # v1.5.3 (2026-05-26) diff --git a/docs/02-usage/060_dashboard.md b/docs/02-usage/060_dashboard.md index ae11fd4d..50a1dc16 100644 --- a/docs/02-usage/060_dashboard.md +++ b/docs/02-usage/060_dashboard.md @@ -25,7 +25,7 @@ The dashboard is a web application, which is opened in one of three ways: * via a tray manager that aggregates multiple instances (on supported platforms) * via your default web browser (supported on all platforms) -Configure your preferred interface via the setting `web_dashoard_interface` in [Serena's global configuration file](global-config) (see below). +Configure your preferred interface via the setting `web_dashboard_interface` in [Serena's global configuration file](global-config) (see below). By default, the dashboard can be accessed at `http://localhost:24282/dashboard/index.html`, but a higher port may be used if the default port is unavailable/multiple instances are running. @@ -82,4 +82,4 @@ Via its menu, it furthermore allows you to The tool is mainly supported on Windows, but it may work on some Linux systems as well (depending on your desktop environment). -To enable the tool, set `gui_log_window` to `true` in Serena's [global configuration file](global-config). \ No newline at end of file +To enable the tool, set `gui_log_window` to `true` in Serena's [global configuration file](global-config). diff --git a/flake.nix b/flake.nix index 9550e4ff..3cdd06f7 100644 --- a/flake.nix +++ b/flake.nix @@ -50,27 +50,79 @@ sourcePreference = "wheel"; # or sourcePreference = "sdist"; }; - pyprojectOverrides = final: prev: { - # Add setuptools for packages that need it during build - ruamel-yaml-clib = prev.ruamel-yaml-clib.overrideAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ - final.setuptools - ]; - }); - proxy-tools = prev.proxy-tools.overrideAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ - final.setuptools - ]; - }); - pywebview = prev.pywebview.overrideAttrs (old: { - nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ - final.setuptools - final.setuptools-scm - ]; - }); - }; - python = pkgs.python311; + pyprojectHacks = pkgs.callPackage pyproject-nix.build.hacks {}; + + pyprojectOverrides = final: prev: + { + # Add setuptools for packages that need it during build + ruamel-yaml-clib = prev.ruamel-yaml-clib.overrideAttrs (old: { + nativeBuildInputs = + (old.nativeBuildInputs or []) + ++ [ + final.setuptools + ]; + }); + proxy-tools = prev.proxy-tools.overrideAttrs (old: { + nativeBuildInputs = + (old.nativeBuildInputs or []) + ++ [ + final.setuptools + ]; + }); + pywebview = prev.pywebview.overrideAttrs (old: { + nativeBuildInputs = + (old.nativeBuildInputs or []) + ++ [ + final.setuptools + final.setuptools-scm + ]; + }); + } + // lib.optionalAttrs pkgs.stdenv.isLinux { + # pyproject-nix's virtualenv resolver follows pyproject-style + # passthru.dependencies, while these GI bindings are already packaged + # by nixpkgs' Python infrastructure. nixpkgsPrebuilt is the upstream + # adapter for that case: + # https://pyproject-nix.github.io/pyproject.nix/builders/hacks.html#using-prebuilt-packages-from-nixpkgs + pycairo = pyprojectHacks.nixpkgsPrebuilt { + from = python.pkgs.pycairo; + prev = { + passthru = { + dependencies = {}; + optional-dependencies = {}; + dependency-groups = {}; + }; + }; + }; + pygobject3 = pyprojectHacks.nixpkgsPrebuilt { + from = python.pkgs.pygobject3; + prev = { + passthru = { + dependencies = { + pycairo = []; + }; + optional-dependencies = {}; + dependency-groups = {}; + }; + }; + }; + + # pystray has an optional AppIndicator backend on Linux. Its uv lock + # metadata does not encode the GI dependency, so add the runtime edge + # here while keeping pystray itself lockfile-driven. + pystray = prev.pystray.overrideAttrs (old: { + passthru = + (old.passthru or {}) + // { + dependencies = + (old.passthru.dependencies or {}) + // { + pygobject3 = []; + }; + }; + }); + }; pythonSet = (pkgs.callPackage pyproject-nix.build.packages { @@ -88,20 +140,48 @@ packages = { serena-env = pythonSet.mkVirtualEnv "serena-env" workspace.deps.default; - serena = pkgs.runCommand "serena" { - meta = { - description = "A powerful coding agent toolkit providing semantic retrieval and editing capabilities (MCP server & Agno integration)"; - homepage = "https://oraios.github.io/serena"; - changelog = "https://github.com/oraios/serena/blob/main/CHANGELOG.md"; - mainProgram = "serena"; - license = pkgs.lib.licenses.mit; - platforms = lib.platforms.all; - }; - } '' - mkdir -p $out/bin - ln -s ${packages.serena-env}/bin/serena $out/bin/serena - ln -s ${packages.serena-env}/bin/serena-hooks $out/bin/serena-hooks - ''; + serena = pkgs.stdenv.mkDerivation { + name = "serena"; + dontUnpack = true; + dontWrapGApps = true; + nativeBuildInputs = + [pkgs.makeWrapper] + ++ lib.optionals pkgs.stdenv.isLinux [ + pkgs.wrapGAppsHook3 + pkgs.gobject-introspection + ]; + buildInputs = lib.optionals pkgs.stdenv.isLinux [ + pkgs.gtk3 + pkgs.libayatana-appindicator + ]; + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + ${ + lib.optionalString (!pkgs.stdenv.isLinux) '' + ln -s ${packages.serena-env}/bin/serena $out/bin/serena + '' + } + ln -s ${packages.serena-env}/bin/serena-hooks $out/bin/serena-hooks + + runHook postInstall + ''; + # Run the GApps fixup phase so the wrapper gets GI_TYPELIB_PATH for + # Gtk and AyatanaAppIndicator3. This is the same pattern nixpkgs uses + # for pystray consumers such as plex-mpv-shim and jellyfin-mpv-shim. + preFixup = lib.optionalString pkgs.stdenv.isLinux '' + makeWrapper ${packages.serena-env}/bin/serena $out/bin/serena "''${gappsWrapperArgs[@]}" + ''; + meta = { + description = "A powerful coding agent toolkit providing semantic retrieval and editing capabilities (MCP server & Agno integration)"; + homepage = "https://oraios.github.io/serena"; + changelog = "https://github.com/oraios/serena/blob/main/CHANGELOG.md"; + mainProgram = "serena"; + license = pkgs.lib.licenses.mit; + platforms = lib.platforms.all; + }; + }; default = packages.serena; }; diff --git a/src/serena/resources/serena_config.template.yml b/src/serena/resources/serena_config.template.yml index 8664fea3..36f22bf3 100644 --- a/src/serena/resources/serena_config.template.yml +++ b/src/serena/resources/serena_config.template.yml @@ -61,6 +61,8 @@ web_dashboard_open_on_launch: True # opening the dashboard in browser tabs when selected from the tray menu. # This is EXPERIMENTAL. It is tested on Windows only. We will establish macOS support, but it is yet untested. # On Linux, this cannot be universally supported, but it may work in some desktop environments. +# On NixOS, when using the package from flake.nix, both modern AppIndicator trays as well as +# older Xorg-/XEmbed-based trays should be supported. # See https://oraios.github.io/serena/02-usage/060_dashboard.html web_dashboard_interface: