diff --git a/flake.nix b/flake.nix index df416758..317a965b 100644 --- a/flake.nix +++ b/flake.nix @@ -171,25 +171,40 @@ inherit (nixpkgs) lib; inherit (nixpkgs.lib) nixosSystem; }; - # Daemon + harness + MCP server binaries. Excludes hivectl and - # hive-forge which are their own derivations below — so each bin - # is compiled exactly once. `packages.default` joins all three - # via symlinkJoin; no binary is compiled more than once regardless - # of which packages the operator builds together. + # One package per daemon/harness/MCP-server binary — matches the + # `hivectl` / `hive-forge` split below rather than grouping them + # into a single derivation. Consumers (agent containers, host + # module, `nix profile install`) depend on exactly the binaries + # 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 # (carries the hyperhive-assets build input for the prompt-template # assertions in hive-ag3nt::prompt::tests). Keeping them out of the # binary derivations means a prompt edit doesn't bust the cargo cache. - daemonBins = craneLib.buildPackage { - src = cleanSrc; - inherit cargoArtifacts nativeBuildInputs; - 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"; - pname = "hyperhive-daemon"; - version = "0.1.0"; - meta.description = "hyperhive daemon + privileged helper + agent harness + bash/matrix MCP servers"; - doCheck = false; - }; + mkDaemonBin = + bin: description: + craneLib.buildPackage { + src = cleanSrc; + inherit cargoArtifacts nativeBuildInputs; + cargoExtraArgs = "--bin ${bin}"; + pname = bin; + 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 # `wg` wrapper) without the daemon binaries. Suitable for # `nix profile install .#hivectl` / `environment.systemPackages @@ -248,26 +263,39 @@ default = pkgs.symlinkJoin { name = "hyperhive"; paths = [ - daemonBins + hiveC0rePkg + hivePrivPkg + hiveAgentPkg + hiveAgentMcpPkg + hiveAgentWakePkg + hiveBashDaemonPkg + hiveBashMcpPkg + hiveMatrixDaemonPkg + hiveMatrixMcpPkg + hiveMetricPkg hivectlPkg hiveForgePkg ]; }; - # Per-bin split packages — useful for operator workstations that - # only want the CLI(s) without the daemon binaries. + # Per-bin split packages. Agent containers depend on the + # 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; hive-forge = hiveForgePkg; - # The daemon/harness/MCP bins alone, no `hivectl` and no second - # `hive-forge` copy. Agent containers use this (via the - # `hyperhive-daemon` overlay output below) instead of `default` — - # they need `hive-agent{,-mcp,-wake}` / - # `hive-bash-{daemon,mcp}` / `hive-matrix-{daemon,mcp}`, never - # the operator-only `hivectl` (dials the *host* admin socket, - # unreachable from inside a container, and drags in - # `wireguard-tools` as a wrapper dep) or a redundant `hive-forge` - # (already on agent PATH via `hive-forge-tools.nix`) — this is - # the fix for the agent-derivation-bloat report. - daemonBins = daemonBins; + hive-c0re = hiveC0rePkg; + hive-priv = hivePrivPkg; + hive-agent = hiveAgentPkg; + hive-agent-mcp = hiveAgentMcpPkg; + hive-agent-wake = hiveAgentWakePkg; + hive-bash-daemon = hiveBashDaemonPkg; + hive-bash-mcp = hiveBashMcpPkg; + hive-matrix-daemon = hiveMatrixDaemonPkg; + hive-matrix-mcp = hiveMatrixMcpPkg; + hive-metric = hiveMetricPkg; # Bundled browser assets — see ./nix/frontend.nix. Output is # $out/{dashboard,agent}/ which the Rust binaries serve via # tower_http::ServeDir. @@ -327,10 +355,21 @@ overlays = { default = final: prev: { hyperhive = self.packages.${prev.stdenv.hostPlatform.system}.default; - # Agent-scoped subset of `hyperhive` — daemon/harness/MCP bins - # only, no `hivectl` / no redundant `hive-forge` copy. See - # `packages..daemonBins` above. - hyperhive-daemon = self.packages.${prev.stdenv.hostPlatform.system}.daemonBins; + # Per-binary daemon/harness/MCP-server packages, exposed via the + # overlay so container nix evaluations can depend on exactly the + # bin(s) they need instead of the full `hyperhive` bundle — see + # `packages..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 # $out/{dashboard,agent}/; consumers pick the surface they # need. Exposed via the overlay so containers' nix evaluations diff --git a/nix/templates/harness-base.nix b/nix/templates/harness-base.nix index c03311b4..f85fb7a0 100644 --- a/nix/templates/harness-base.nix +++ b/nix/templates/harness-base.nix @@ -1276,7 +1276,7 @@ in hyperhive.extraMcpServers = lib.mkMerge [ { bash = lib.mkDefault { - command = "${pkgs.hyperhive-daemon}/bin/hive-bash-mcp"; + command = "${pkgs.hive-bash-mcp}/bin/hive-bash-mcp"; args = [ ]; env.HIVE_BASH_SOCKET = "/run/hive-bash/socket"; allowedTools = [ "*" ]; @@ -1284,7 +1284,7 @@ in } (lib.mkIf config.hyperhive.matrix.enable { matrix = lib.mkDefault { - command = "${pkgs.hyperhive-daemon}/bin/hive-matrix-mcp"; + command = "${pkgs.hive-matrix-mcp}/bin/hive-matrix-mcp"; args = [ ]; # Same socket path the hive-matrix-daemon service binds # via its `RuntimeDirectory = "hive-matrix"`. Keeps the @@ -1636,17 +1636,24 @@ in environment.systemPackages = with pkgs; [ - # Agent-scoped subset of `pkgs.hyperhive` — daemon/harness/MCP - # bins the harness itself execs (see the ExecStarts above) plus - # whatever else lands on PATH for claude's Bash tool. Deliberately - # NOT the full `pkgs.hyperhive` bundle: that also carries `hivectl` - # (a host-admin CLI that dials the *host* admin socket — useless - # and unreachable from inside a container — wrapped with - # `wireguard-tools` for `hivectl wg`) and a second, redundant - # `hive-forge` copy (already provided below via + # Per-bin split packages (see flake.nix `packages..hive-*`) + # rather than the full `pkgs.hyperhive` bundle — that bundle also + # carries `hivectl` (a host-admin CLI that dials the *host* admin + # socket — useless and unreachable from inside a container — + # wrapped with `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 - # functional upside inside a container. - hyperhive-daemon + # functional upside inside a container. The daemon/harness/MCP + # 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 bashInteractive coreutils-full @@ -1956,7 +1963,7 @@ in HIVE_ICON_PNG = "${iconPng}"; }; serviceConfig = { - ExecStart = "${pkgs.hyperhive-daemon}/bin/hive-matrix-daemon"; + ExecStart = "${pkgs.hive-matrix-daemon}/bin/hive-matrix-daemon"; SyslogIdentifier = "hive-matrix-daemon"; Restart = "on-failure"; RestartSec = 5; @@ -2012,7 +2019,7 @@ in # less robust if the two vars ever diverge. }; serviceConfig = { - ExecStart = "${pkgs.hyperhive-daemon}/bin/hive-bash-daemon"; + ExecStart = "${pkgs.hive-bash-daemon}/bin/hive-bash-daemon"; SyslogIdentifier = "hive-bash-daemon"; Restart = "on-failure"; RestartSec = 3; @@ -2046,7 +2053,7 @@ in before = [ "hive-ag3nt.service" ]; environment.RUST_LOG = "info"; 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"; # `always` (not `on-failure`): this endpoint is load-bearing — the # sole hyperhive-MCP transport, so a down window is total @@ -2177,7 +2184,7 @@ in HIVE_EXTRA_WEB_PROXIES = builtins.toJSON config.hyperhive.extraWebProxies; }; serviceConfig = { - ExecStart = "${pkgs.hyperhive-daemon}/bin/${binary}"; + ExecStart = "${pkgs.hive-agent}/bin/${binary}"; # Pin the journal identity to the binary name (otherwise systemd # derives SyslogIdentifier from the ExecStart basename). SyslogIdentifier = binary;