nix: wire the independent hive-subagent-daemon systemd unit and MCP server
This commit is contained in:
parent
7699db6500
commit
c280664d74
6 changed files with 77 additions and 2 deletions
|
|
@ -93,6 +93,7 @@
|
||||||
hive-matrix-daemon
|
hive-matrix-daemon
|
||||||
hive-metric
|
hive-metric
|
||||||
hive-screen-mcp
|
hive-screen-mcp
|
||||||
|
hive-subagent-daemon
|
||||||
assets
|
assets
|
||||||
frontend
|
frontend
|
||||||
reference-docs
|
reference-docs
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ pub(super) async fn get_journal(
|
||||||
"hive-agent.service",
|
"hive-agent.service",
|
||||||
"hive-mcp-http.service",
|
"hive-mcp-http.service",
|
||||||
"hive-bash-daemon.service",
|
"hive-bash-daemon.service",
|
||||||
|
"hive-subagent-daemon.service",
|
||||||
"hive-matrix-daemon.service",
|
"hive-matrix-daemon.service",
|
||||||
];
|
];
|
||||||
let unit = if u.ends_with(".service") {
|
let unit = if u.ends_with(".service") {
|
||||||
|
|
|
||||||
|
|
@ -203,7 +203,8 @@
|
||||||
# unreachable from inside a container — wrapped with
|
# unreachable from inside a container — wrapped with
|
||||||
# `wireguard-tools` for `hivectl wg`). The daemon/harness/MCP bins
|
# `wireguard-tools` for `hivectl wg`). The daemon/harness/MCP bins
|
||||||
# the harness execs (hive-agent{,-mcp}, hive-bash-daemon,
|
# the harness execs (hive-agent{,-mcp}, hive-bash-daemon,
|
||||||
# hive-matrix-daemon, hive-matrix-mcp) are wired via their own
|
# hive-subagent-daemon, hive-matrix-daemon, hive-matrix-mcp) are
|
||||||
|
# wired via their own
|
||||||
# ExecStart/command lines in the sibling modules — they don't need
|
# ExecStart/command lines in the sibling modules — they don't need
|
||||||
# to be on PATH too. Only this one is actually looked up on PATH
|
# to be on PATH too. Only this one is actually looked up on PATH
|
||||||
# by claude/shell code inside the container:
|
# by claude/shell code inside the container:
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,23 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options.hyperhive.mcp.subagentHttpPort = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 8793;
|
||||||
|
example = 8794;
|
||||||
|
description = ''
|
||||||
|
Loopback port `hive-subagent-daemon` serves its MCP tools
|
||||||
|
(`start`/`continue`/`interrupt`) on. Independent daemon (own crate,
|
||||||
|
`hive-subagent-mcp`) — a subagent spawns a full nested `claude`
|
||||||
|
process, a much heavier capability than a bash command, worth its own
|
||||||
|
deployable/restartable unit. Same shape/reasoning as
|
||||||
|
`hyperhive.mcp.bashHttpPort` otherwise: sole transport, self-healing
|
||||||
|
restart, loopback-only so no auth token is needed. Shipped default-on
|
||||||
|
for every agent today, same as `bash` — expected to become a real
|
||||||
|
opt-in capability gate later, not yet.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# Assert the transport-specific required field is actually set —
|
# Assert the transport-specific required field is actually set —
|
||||||
# `command`/`url` are both `nullOr` so the submodule schema stays
|
# `command`/`url` are both `nullOr` so the submodule schema stays
|
||||||
|
|
@ -225,6 +242,17 @@ in
|
||||||
allowedTools = [ "*" ];
|
allowedTools = [ "*" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Auto-inject the subagent MCP server — default-on for every agent for
|
||||||
|
# now (operator's call: "default on for now, should be a capability
|
||||||
|
# later" — not gated behind an enable option yet, unlike `matrix.nix`'s
|
||||||
|
# pattern). `lib.mkDefault` so an agent.nix can still override/disable
|
||||||
|
# the entry in the meantime.
|
||||||
|
hyperhive.extraMcpServers.subagent = lib.mkDefault {
|
||||||
|
type = "http";
|
||||||
|
url = "http://127.0.0.1:${toString config.hyperhive.mcp.subagentHttpPort}/mcp";
|
||||||
|
allowedTools = [ "*" ];
|
||||||
|
};
|
||||||
|
|
||||||
environment.etc."hyperhive/extra-mcp.json".text = builtins.toJSON config.hyperhive.extraMcpServers;
|
environment.etc."hyperhive/extra-mcp.json".text = builtins.toJSON config.hyperhive.extraMcpServers;
|
||||||
|
|
||||||
environment.etc."hyperhive/send-allow.json".text =
|
environment.etc."hyperhive/send-allow.json".text =
|
||||||
|
|
@ -278,6 +306,49 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Subagent task runner daemon — independent of `hive-bash-daemon` (own
|
||||||
|
# crate, own process): spawns nested claude sessions on request, serves
|
||||||
|
# the `start`/`continue`/`interrupt` MCP tools directly over
|
||||||
|
# streamable-http on `hyperhive.mcp.subagentHttpPort`. No task files —
|
||||||
|
# this daemon's only state is an in-memory map of currently-running
|
||||||
|
# processes, live only as long as the process is (see
|
||||||
|
# `hive-subagent-mcp/src/session.rs`'s module doc); a restart stops
|
||||||
|
# whatever's running, the actual claude session survives independently.
|
||||||
|
systemd.services.hive-subagent-daemon = {
|
||||||
|
description = "subagent task runner + MCP daemon for hive-subagent";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "hive-agent.service" ];
|
||||||
|
# A subagent task runs its own nested `claude` invocation (via
|
||||||
|
# `hive-claude`), which needs to resolve `claude` itself off PATH —
|
||||||
|
# same reasoning as `hive-bash-daemon`'s `path` above, even though
|
||||||
|
# this daemon never shells out to `bash -c` directly.
|
||||||
|
path = [
|
||||||
|
"/run/wrappers"
|
||||||
|
"/run/current-system/sw"
|
||||||
|
];
|
||||||
|
environment = {
|
||||||
|
# Same in-agent todo socket as `hive-bash-daemon` — both push task
|
||||||
|
# todos to the one harness socket. Must match the harness's
|
||||||
|
# HIVE_AGENT_SOCKET (agent-service.nix).
|
||||||
|
HIVE_AGENT_SOCKET = "/run/hive-agent/${userName}/agent.sock";
|
||||||
|
RUST_LOG = "info";
|
||||||
|
# HYPERHIVE_HARNESS_DIR / HYPERHIVE_STATE_DIR: see
|
||||||
|
# `hive-bash-daemon`'s own comment above — same global injection,
|
||||||
|
# same reasoning.
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
ExecStart = "${config.hyperhive.packages.hive-subagent-daemon}/bin/hive-subagent-daemon --http 127.0.0.1:${toString config.hyperhive.mcp.subagentHttpPort}";
|
||||||
|
SyslogIdentifier = "hive-subagent-daemon";
|
||||||
|
# `always`, same reasoning as `hive-bash-daemon`: the MCP tool is
|
||||||
|
# served in-process, so a down window is total loss of
|
||||||
|
# `spawn_subagent` with no stdio fallback.
|
||||||
|
Restart = "always";
|
||||||
|
RestartSec = 3;
|
||||||
|
User = userName;
|
||||||
|
Group = userName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# Persistent streamable-http MCP daemon for the built-in hyperhive
|
# Persistent streamable-http MCP daemon for the built-in hyperhive
|
||||||
# surface — the *sole* transport for that surface; always
|
# surface — the *sole* transport for that surface; always
|
||||||
# wired. Long-lived so claude reconnects to the stable URL each turn
|
# wired. Long-lived so claude reconnects to the stable URL each turn
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
description = ''
|
description = ''
|
||||||
hyperhive package outputs consumed by the harness modules: the
|
hyperhive package outputs consumed by the harness modules: the
|
||||||
per-binary daemon/CLI packages (`hive-agent`, `hive-agent-mcp`,
|
per-binary daemon/CLI packages (`hive-agent`, `hive-agent-mcp`,
|
||||||
`hive-bash-daemon`,
|
`hive-bash-daemon`, `hive-subagent-daemon`,
|
||||||
`hive-forge`, `hive-forge-notify`, `hive-github-notify`,
|
`hive-forge`, `hive-forge-notify`, `hive-github-notify`,
|
||||||
`hive-matrix-daemon`,
|
`hive-matrix-daemon`,
|
||||||
`hive-metric`, `hive-screen-mcp`) plus the `assets`, `frontend`,
|
`hive-metric`, `hive-screen-mcp`) plus the `assets`, `frontend`,
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ let
|
||||||
hive-agent = "hyperhive in-container agent harness serve loop";
|
hive-agent = "hyperhive in-container agent harness serve loop";
|
||||||
hive-agent-mcp = "hyperhive agent-surface MCP server";
|
hive-agent-mcp = "hyperhive agent-surface MCP server";
|
||||||
hive-bash-daemon = "hyperhive per-agent bash-task runner daemon (serves its MCP tools directly over streamable-http)";
|
hive-bash-daemon = "hyperhive per-agent bash-task runner daemon (serves its MCP tools directly over streamable-http)";
|
||||||
|
hive-subagent-daemon = "hyperhive per-agent claude-subagent task runner daemon (serves its MCP tools directly over streamable-http)";
|
||||||
hive-matrix-daemon = "hyperhive per-agent matrix-sdk daemon (serves its MCP tools directly over streamable-http)";
|
hive-matrix-daemon = "hyperhive per-agent matrix-sdk daemon (serves its MCP tools directly over streamable-http)";
|
||||||
hive-metric = "hyperhive agent-emitted custom metrics CLI";
|
hive-metric = "hyperhive agent-emitted custom metrics CLI";
|
||||||
hive-screen-mcp = "hyperhive screen MCP bridge (screenshot + input for GUI agents)";
|
hive-screen-mcp = "hyperhive screen MCP bridge (screenshot + input for GUI agents)";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue