fix(#2399): split daemon/harness/MCP bins into per-binary packages
mara: "no, do split packages for the separate daemons" — instead of grouping all daemon/harness/MCP bins into one hyperhive-daemon derivation, each bin (hive-c0re, hive-priv, hive-agent, hive-agent-mcp, hive-agent-wake, hive-bash-daemon, hive-bash-mcp, hive-matrix-daemon, hive-matrix-mcp, hive-metric) is now its own named package + overlay output, matching the existing hivectl / hive-forge split. harness-base.nix's ExecStart/command lines now point at the specific pkgs.hive-* each ExecStart needs, and environment.systemPackages only carries the two bins actually PATH-looked-up in-container (hive-agent-wake, hive-metric) instead of the whole bundle.
This commit is contained in:
parent
5c08abc1b2
commit
650224c9c6
2 changed files with 94 additions and 48 deletions
103
flake.nix
103
flake.nix
|
|
@ -171,25 +171,40 @@
|
||||||
inherit (nixpkgs) lib;
|
inherit (nixpkgs) lib;
|
||||||
inherit (nixpkgs.lib) nixosSystem;
|
inherit (nixpkgs.lib) nixosSystem;
|
||||||
};
|
};
|
||||||
# Daemon + harness + MCP server binaries. Excludes hivectl and
|
# One package per daemon/harness/MCP-server binary — matches the
|
||||||
# hive-forge which are their own derivations below — so each bin
|
# `hivectl` / `hive-forge` split below rather than grouping them
|
||||||
# is compiled exactly once. `packages.default` joins all three
|
# into a single derivation. Consumers (agent containers, host
|
||||||
# via symlinkJoin; no binary is compiled more than once regardless
|
# module, `nix profile install`) depend on exactly the binaries
|
||||||
# of which packages the operator builds together.
|
# they need instead of an all-or-nothing bundle. All share
|
||||||
|
# `cargoArtifacts` (built once via `buildDepsOnly` above), so
|
||||||
|
# splitting doesn't cost extra rustc invocations — each call
|
||||||
|
# below just asks crane to build+link its one requested `--bin`.
|
||||||
#
|
#
|
||||||
# Tests are kept in the separate `checks.cargo-test` derivation
|
# Tests are kept in the separate `checks.cargo-test` derivation
|
||||||
# (carries the hyperhive-assets build input for the prompt-template
|
# (carries the hyperhive-assets build input for the prompt-template
|
||||||
# assertions in hive-ag3nt::prompt::tests). Keeping them out of the
|
# assertions in hive-ag3nt::prompt::tests). Keeping them out of the
|
||||||
# binary derivations means a prompt edit doesn't bust the cargo cache.
|
# binary derivations means a prompt edit doesn't bust the cargo cache.
|
||||||
daemonBins = craneLib.buildPackage {
|
mkDaemonBin =
|
||||||
src = cleanSrc;
|
bin: description:
|
||||||
inherit cargoArtifacts nativeBuildInputs;
|
craneLib.buildPackage {
|
||||||
cargoExtraArgs = "--bin hive-c0re --bin hive-priv --bin hive-agent --bin hive-agent-mcp --bin hive-agent-wake --bin hive-bash-daemon --bin hive-bash-mcp --bin hive-matrix-daemon --bin hive-matrix-mcp --bin hive-metric";
|
src = cleanSrc;
|
||||||
pname = "hyperhive-daemon";
|
inherit cargoArtifacts nativeBuildInputs;
|
||||||
version = "0.1.0";
|
cargoExtraArgs = "--bin ${bin}";
|
||||||
meta.description = "hyperhive daemon + privileged helper + agent harness + bash/matrix MCP servers";
|
pname = bin;
|
||||||
doCheck = false;
|
version = "0.1.0";
|
||||||
};
|
meta.description = description;
|
||||||
|
doCheck = false;
|
||||||
|
};
|
||||||
|
hiveC0rePkg = mkDaemonBin "hive-c0re" "hyperhive host coordinator daemon";
|
||||||
|
hivePrivPkg = mkDaemonBin "hive-priv" "hyperhive privileged root helper";
|
||||||
|
hiveAgentPkg = mkDaemonBin "hive-agent" "hyperhive in-container agent harness serve loop";
|
||||||
|
hiveAgentMcpPkg = mkDaemonBin "hive-agent-mcp" "hyperhive agent-surface MCP server";
|
||||||
|
hiveAgentWakePkg = mkDaemonBin "hive-agent-wake" "hyperhive external wake CLI — push a message into an agent's own inbox";
|
||||||
|
hiveBashDaemonPkg = mkDaemonBin "hive-bash-daemon" "hyperhive per-agent bash-task runner daemon";
|
||||||
|
hiveBashMcpPkg = mkDaemonBin "hive-bash-mcp" "hyperhive bash-task MCP bridge";
|
||||||
|
hiveMatrixDaemonPkg = mkDaemonBin "hive-matrix-daemon" "hyperhive per-agent matrix-sdk daemon";
|
||||||
|
hiveMatrixMcpPkg = mkDaemonBin "hive-matrix-mcp" "hyperhive matrix MCP bridge";
|
||||||
|
hiveMetricPkg = mkDaemonBin "hive-metric" "hyperhive agent-emitted custom metrics CLI";
|
||||||
# Operator CLI — ships `hivectl` (with shell completions and the
|
# Operator CLI — ships `hivectl` (with shell completions and the
|
||||||
# `wg` wrapper) without the daemon binaries. Suitable for
|
# `wg` wrapper) without the daemon binaries. Suitable for
|
||||||
# `nix profile install .#hivectl` / `environment.systemPackages
|
# `nix profile install .#hivectl` / `environment.systemPackages
|
||||||
|
|
@ -248,26 +263,39 @@
|
||||||
default = pkgs.symlinkJoin {
|
default = pkgs.symlinkJoin {
|
||||||
name = "hyperhive";
|
name = "hyperhive";
|
||||||
paths = [
|
paths = [
|
||||||
daemonBins
|
hiveC0rePkg
|
||||||
|
hivePrivPkg
|
||||||
|
hiveAgentPkg
|
||||||
|
hiveAgentMcpPkg
|
||||||
|
hiveAgentWakePkg
|
||||||
|
hiveBashDaemonPkg
|
||||||
|
hiveBashMcpPkg
|
||||||
|
hiveMatrixDaemonPkg
|
||||||
|
hiveMatrixMcpPkg
|
||||||
|
hiveMetricPkg
|
||||||
hivectlPkg
|
hivectlPkg
|
||||||
hiveForgePkg
|
hiveForgePkg
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
# Per-bin split packages — useful for operator workstations that
|
# Per-bin split packages. Agent containers depend on the
|
||||||
# only want the CLI(s) without the daemon binaries.
|
# individual bins they actually exec/PATH-need (see
|
||||||
|
# `harness-base.nix`) instead of the `default` bundle — that
|
||||||
|
# keeps `hivectl` (dials the *host* admin socket, unreachable
|
||||||
|
# from inside a container, drags in `wireguard-tools`) and a
|
||||||
|
# redundant `hive-forge` copy (already on agent PATH via
|
||||||
|
# `hive-forge-tools.nix`) out of every agent's closure.
|
||||||
hivectl = hivectlPkg;
|
hivectl = hivectlPkg;
|
||||||
hive-forge = hiveForgePkg;
|
hive-forge = hiveForgePkg;
|
||||||
# The daemon/harness/MCP bins alone, no `hivectl` and no second
|
hive-c0re = hiveC0rePkg;
|
||||||
# `hive-forge` copy. Agent containers use this (via the
|
hive-priv = hivePrivPkg;
|
||||||
# `hyperhive-daemon` overlay output below) instead of `default` —
|
hive-agent = hiveAgentPkg;
|
||||||
# they need `hive-agent{,-mcp,-wake}` /
|
hive-agent-mcp = hiveAgentMcpPkg;
|
||||||
# `hive-bash-{daemon,mcp}` / `hive-matrix-{daemon,mcp}`, never
|
hive-agent-wake = hiveAgentWakePkg;
|
||||||
# the operator-only `hivectl` (dials the *host* admin socket,
|
hive-bash-daemon = hiveBashDaemonPkg;
|
||||||
# unreachable from inside a container, and drags in
|
hive-bash-mcp = hiveBashMcpPkg;
|
||||||
# `wireguard-tools` as a wrapper dep) or a redundant `hive-forge`
|
hive-matrix-daemon = hiveMatrixDaemonPkg;
|
||||||
# (already on agent PATH via `hive-forge-tools.nix`) — this is
|
hive-matrix-mcp = hiveMatrixMcpPkg;
|
||||||
# the fix for the agent-derivation-bloat report.
|
hive-metric = hiveMetricPkg;
|
||||||
daemonBins = daemonBins;
|
|
||||||
# Bundled browser assets — see ./nix/frontend.nix. Output is
|
# Bundled browser assets — see ./nix/frontend.nix. Output is
|
||||||
# $out/{dashboard,agent}/ which the Rust binaries serve via
|
# $out/{dashboard,agent}/ which the Rust binaries serve via
|
||||||
# tower_http::ServeDir.
|
# tower_http::ServeDir.
|
||||||
|
|
@ -327,10 +355,21 @@
|
||||||
overlays = {
|
overlays = {
|
||||||
default = final: prev: {
|
default = final: prev: {
|
||||||
hyperhive = self.packages.${prev.stdenv.hostPlatform.system}.default;
|
hyperhive = self.packages.${prev.stdenv.hostPlatform.system}.default;
|
||||||
# Agent-scoped subset of `hyperhive` — daemon/harness/MCP bins
|
# Per-binary daemon/harness/MCP-server packages, exposed via the
|
||||||
# only, no `hivectl` / no redundant `hive-forge` copy. See
|
# overlay so container nix evaluations can depend on exactly the
|
||||||
# `packages.<system>.daemonBins` above.
|
# bin(s) they need instead of the full `hyperhive` bundle — see
|
||||||
hyperhive-daemon = self.packages.${prev.stdenv.hostPlatform.system}.daemonBins;
|
# `packages.<system>.hive-*` above and their use in
|
||||||
|
# `harness-base.nix`.
|
||||||
|
hive-c0re = self.packages.${prev.stdenv.hostPlatform.system}.hive-c0re;
|
||||||
|
hive-priv = self.packages.${prev.stdenv.hostPlatform.system}.hive-priv;
|
||||||
|
hive-agent = self.packages.${prev.stdenv.hostPlatform.system}.hive-agent;
|
||||||
|
hive-agent-mcp = self.packages.${prev.stdenv.hostPlatform.system}.hive-agent-mcp;
|
||||||
|
hive-agent-wake = self.packages.${prev.stdenv.hostPlatform.system}.hive-agent-wake;
|
||||||
|
hive-bash-daemon = self.packages.${prev.stdenv.hostPlatform.system}.hive-bash-daemon;
|
||||||
|
hive-bash-mcp = self.packages.${prev.stdenv.hostPlatform.system}.hive-bash-mcp;
|
||||||
|
hive-matrix-daemon = self.packages.${prev.stdenv.hostPlatform.system}.hive-matrix-daemon;
|
||||||
|
hive-matrix-mcp = self.packages.${prev.stdenv.hostPlatform.system}.hive-matrix-mcp;
|
||||||
|
hive-metric = self.packages.${prev.stdenv.hostPlatform.system}.hive-metric;
|
||||||
# Bundled frontend dist (see ./nix/frontend.nix). Output is
|
# Bundled frontend dist (see ./nix/frontend.nix). Output is
|
||||||
# $out/{dashboard,agent}/; consumers pick the surface they
|
# $out/{dashboard,agent}/; consumers pick the surface they
|
||||||
# need. Exposed via the overlay so containers' nix evaluations
|
# need. Exposed via the overlay so containers' nix evaluations
|
||||||
|
|
|
||||||
|
|
@ -1276,7 +1276,7 @@ in
|
||||||
hyperhive.extraMcpServers = lib.mkMerge [
|
hyperhive.extraMcpServers = lib.mkMerge [
|
||||||
{
|
{
|
||||||
bash = lib.mkDefault {
|
bash = lib.mkDefault {
|
||||||
command = "${pkgs.hyperhive-daemon}/bin/hive-bash-mcp";
|
command = "${pkgs.hive-bash-mcp}/bin/hive-bash-mcp";
|
||||||
args = [ ];
|
args = [ ];
|
||||||
env.HIVE_BASH_SOCKET = "/run/hive-bash/socket";
|
env.HIVE_BASH_SOCKET = "/run/hive-bash/socket";
|
||||||
allowedTools = [ "*" ];
|
allowedTools = [ "*" ];
|
||||||
|
|
@ -1284,7 +1284,7 @@ in
|
||||||
}
|
}
|
||||||
(lib.mkIf config.hyperhive.matrix.enable {
|
(lib.mkIf config.hyperhive.matrix.enable {
|
||||||
matrix = lib.mkDefault {
|
matrix = lib.mkDefault {
|
||||||
command = "${pkgs.hyperhive-daemon}/bin/hive-matrix-mcp";
|
command = "${pkgs.hive-matrix-mcp}/bin/hive-matrix-mcp";
|
||||||
args = [ ];
|
args = [ ];
|
||||||
# Same socket path the hive-matrix-daemon service binds
|
# Same socket path the hive-matrix-daemon service binds
|
||||||
# via its `RuntimeDirectory = "hive-matrix"`. Keeps the
|
# via its `RuntimeDirectory = "hive-matrix"`. Keeps the
|
||||||
|
|
@ -1636,17 +1636,24 @@ in
|
||||||
environment.systemPackages =
|
environment.systemPackages =
|
||||||
with pkgs;
|
with pkgs;
|
||||||
[
|
[
|
||||||
# Agent-scoped subset of `pkgs.hyperhive` — daemon/harness/MCP
|
# Per-bin split packages (see flake.nix `packages.<system>.hive-*`)
|
||||||
# bins the harness itself execs (see the ExecStarts above) plus
|
# rather than the full `pkgs.hyperhive` bundle — that bundle also
|
||||||
# whatever else lands on PATH for claude's Bash tool. Deliberately
|
# carries `hivectl` (a host-admin CLI that dials the *host* admin
|
||||||
# NOT the full `pkgs.hyperhive` bundle: that also carries `hivectl`
|
# socket — useless and unreachable from inside a container —
|
||||||
# (a host-admin CLI that dials the *host* admin socket — useless
|
# wrapped with `wireguard-tools` for `hivectl wg`) and a second,
|
||||||
# and unreachable from inside a container — wrapped with
|
# redundant `hive-forge` copy (already provided below via
|
||||||
# `wireguard-tools` for `hivectl wg`) and a second, redundant
|
|
||||||
# `hive-forge` copy (already provided below via
|
|
||||||
# `hive-forge-tools.nix`) — closure bloat + dead surface with no
|
# `hive-forge-tools.nix`) — closure bloat + dead surface with no
|
||||||
# functional upside inside a container.
|
# functional upside inside a container. The daemon/harness/MCP
|
||||||
hyperhive-daemon
|
# bins the harness execs (hive-agent{,-mcp}, hive-bash-daemon,
|
||||||
|
# hive-matrix-daemon, hive-bash-mcp, hive-matrix-mcp) are wired
|
||||||
|
# via their own ExecStart/command lines above with the matching
|
||||||
|
# `pkgs.hive-*` package — they don't need to be on PATH too.
|
||||||
|
# Only these two are actually looked up on PATH by claude/shell
|
||||||
|
# code inside the container: `hive-agent-wake` (external wake CLI,
|
||||||
|
# docs/turn-loop/mcp.md) and `hive-metric` (agent-emitted custom
|
||||||
|
# metrics CLI, docs/observability.md).
|
||||||
|
hive-agent-wake
|
||||||
|
hive-metric
|
||||||
claude-code
|
claude-code
|
||||||
bashInteractive
|
bashInteractive
|
||||||
coreutils-full
|
coreutils-full
|
||||||
|
|
@ -1956,7 +1963,7 @@ in
|
||||||
HIVE_ICON_PNG = "${iconPng}";
|
HIVE_ICON_PNG = "${iconPng}";
|
||||||
};
|
};
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.hyperhive-daemon}/bin/hive-matrix-daemon";
|
ExecStart = "${pkgs.hive-matrix-daemon}/bin/hive-matrix-daemon";
|
||||||
SyslogIdentifier = "hive-matrix-daemon";
|
SyslogIdentifier = "hive-matrix-daemon";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 5;
|
RestartSec = 5;
|
||||||
|
|
@ -2012,7 +2019,7 @@ in
|
||||||
# less robust if the two vars ever diverge.
|
# less robust if the two vars ever diverge.
|
||||||
};
|
};
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.hyperhive-daemon}/bin/hive-bash-daemon";
|
ExecStart = "${pkgs.hive-bash-daemon}/bin/hive-bash-daemon";
|
||||||
SyslogIdentifier = "hive-bash-daemon";
|
SyslogIdentifier = "hive-bash-daemon";
|
||||||
Restart = "on-failure";
|
Restart = "on-failure";
|
||||||
RestartSec = 3;
|
RestartSec = 3;
|
||||||
|
|
@ -2046,7 +2053,7 @@ in
|
||||||
before = [ "hive-ag3nt.service" ];
|
before = [ "hive-ag3nt.service" ];
|
||||||
environment.RUST_LOG = "info";
|
environment.RUST_LOG = "info";
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.hyperhive-daemon}/bin/hive-agent-mcp --http 127.0.0.1:${toString config.hyperhive.mcp.httpPort}";
|
ExecStart = "${pkgs.hive-agent-mcp}/bin/hive-agent-mcp --http 127.0.0.1:${toString config.hyperhive.mcp.httpPort}";
|
||||||
SyslogIdentifier = "hive-mcp-http";
|
SyslogIdentifier = "hive-mcp-http";
|
||||||
# `always` (not `on-failure`): this endpoint is load-bearing — the
|
# `always` (not `on-failure`): this endpoint is load-bearing — the
|
||||||
# sole hyperhive-MCP transport, so a down window is total
|
# sole hyperhive-MCP transport, so a down window is total
|
||||||
|
|
@ -2177,7 +2184,7 @@ in
|
||||||
HIVE_EXTRA_WEB_PROXIES = builtins.toJSON config.hyperhive.extraWebProxies;
|
HIVE_EXTRA_WEB_PROXIES = builtins.toJSON config.hyperhive.extraWebProxies;
|
||||||
};
|
};
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.hyperhive-daemon}/bin/${binary}";
|
ExecStart = "${pkgs.hive-agent}/bin/${binary}";
|
||||||
# Pin the journal identity to the binary name (otherwise systemd
|
# Pin the journal identity to the binary name (otherwise systemd
|
||||||
# derives SyslogIdentifier from the ExecStart basename).
|
# derives SyslogIdentifier from the ExecStart basename).
|
||||||
SyslogIdentifier = binary;
|
SyslogIdentifier = binary;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue