From 246dd19390f8595f119551f982df64ec18cb4260 Mon Sep 17 00:00:00 2001 From: iris Date: Fri, 29 May 2026 02:11:54 +0200 Subject: [PATCH] nix: split static runtime assets into their own derivation (#555) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hoists the project's branding/* + hive-ag3nt/prompts/* out of the rust derivation's src set. Lives as `packages..assets` (also exported as `pkgs.hyperhive-assets` via the default overlay). Output layout: $out/share/hyperhive/branding/{hyperhive,agent-configs}.{svg,png} $out/share/hyperhive/prompts/{system.md,claude-settings.json} `agent-configs.png` is rendered at build time from its SVG via rsvg-convert — same shape as the old `hive-c0re/build.rs` rasteriser, just hoisted into nix so the librsvg dependency stays *here* instead of in the rust derivation. No consumer change yet — the rust binaries still `include_bytes!` their copies from the in-source paths; later commits in this PR cut those over to runtime loads from `$HIVE_ASSETS_DIR/share/hyperhive/`. Why split: `src = ./.;` on the crane derivation invalidates the cargo cache on every edit to anything in the repo, including branding tweaks + prompt edits + docs. Splitting these out is the first step toward dropping the rust src input down to `craneLib.cleanCargoSource ./.` (the eventual end-state in the final commit of this PR). --- flake.nix | 10 +++++++ nix/assets.nix | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 nix/assets.nix diff --git a/flake.nix b/flake.nix index b20c18f9..5309e657 100644 --- a/flake.nix +++ b/flake.nix @@ -106,6 +106,12 @@ frontend = pkgs.callPackage ./nix/frontend.nix { branding-svg = ./branding/hyperhive.svg; }; + # Static runtime assets the rust binaries read via + # `assets::path()` (#555): branding/* + hive-ag3nt/prompts/*, + # plus the rendered agent-configs.png. Split out of the + # rust derivation so a tweak to e.g. system.md doesn't bust + # the cargo cache. + assets = pkgs.callPackage ./nix/assets.nix { }; # Pre-built per-container system closures. Exposed as packages # so operators can `nix build .#agent-base-toplevel` (or wire # them into their host system closure via the @@ -137,6 +143,10 @@ # is applied (manager + agent containers both apply it via # `mkContainer` further down). hyperhive-frontend = self.packages.${prev.stdenv.hostPlatform.system}.frontend; + # Static runtime assets (#555). Exposed alongside the binary + # so the harness module can wire $HIVE_ASSETS_DIR straight + # to `${pkgs.hyperhive-assets}/share/hyperhive`. + hyperhive-assets = self.packages.${prev.stdenv.hostPlatform.system}.assets; }; claude-unstable = final: prev: diff --git a/nix/assets.nix b/nix/assets.nix new file mode 100644 index 00000000..8fc83416 --- /dev/null +++ b/nix/assets.nix @@ -0,0 +1,77 @@ +{ + stdenv, + lib, + librsvg, +}: + +# Static assets the rust workspace reads at runtime: the project's +# branding SVG/PNG family + the claude system-prompt template + +# claude-settings JSON. Lives as its own derivation so a tweak to +# branding/agent-configs.svg or hive-ag3nt/prompts/system.md doesn't +# invalidate the rust derivation's cargo cache (closes #555 follow-up +# to #538 — naersk previously paired with `src = ./.;` invalidating +# every rust build on any branding/prompt edit; crane inherited that +# coupling and this split breaks it cleanly). +# +# Output layout: +# +# $out/share/hyperhive/branding/{hyperhive.svg, hyperhive.png, +# agent-configs.svg, agent-configs.png} +# $out/share/hyperhive/prompts/{system.md, claude-settings.json} +# +# The agent-configs PNG is rendered at build time from the SVG via +# rsvg-convert — same shape as the old `hive-c0re/build.rs` rasteriser, +# just hoisted into nix so the librsvg dependency stays *here* instead +# of in the rust derivation's nativeBuildInputs. + +stdenv.mkDerivation { + pname = "hyperhive-assets"; + version = "0.1.0"; + # `src` is intentionally narrow — only branding/ + the hive-ag3nt/prompts/ + # subdir, NOT the whole tree. Keeps the input hash decoupled from + # rust source / docs / nix module edits. + srcs = [ + ../branding + ../hive-ag3nt/prompts + ]; + # `unpackPhase` would normally extract each src to its own dir; we + # just want them side-by-side, so hand-roll a flat copy. + unpackPhase = '' + runHook preUnpack + cp -r ${../branding} branding + cp -r ${../hive-ag3nt/prompts} prompts + chmod -R u+w branding prompts + runHook postUnpack + ''; + + nativeBuildInputs = [ librsvg ]; + + # No real build step — just render the agent-configs PNG alongside + # its SVG. 300×300 matches branding/hyperhive.png, which is the size + # Forgejo's avatar endpoint accepts without resampling on upload (the + # same constraint hive-c0re/build.rs encoded). + buildPhase = '' + runHook preBuild + rsvg-convert --width 300 --height 300 \ + -o branding/agent-configs.png \ + branding/agent-configs.svg + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out/share/hyperhive + cp -r branding $out/share/hyperhive/branding + cp -r prompts $out/share/hyperhive/prompts + runHook postInstall + ''; + + # Pure data — no executables to fixup, no shared libs to patchelf. + dontFixup = true; + + meta = { + description = "hyperhive static assets (branding + claude prompts)"; + homepage = "https://forge.darkest.space/hyperhive/hyperhive"; + license = lib.licenses.mit; + }; +}