refactor(hive-ag3nt): split hive bin into hive-agent / hive-agent-mcp / hive-agent-wake

This commit is contained in:
müde 2026-07-06 23:48:05 +02:00
commit 5b062dca55
14 changed files with 182 additions and 144 deletions

View file

@ -214,7 +214,8 @@ nspawn agent. Open questions, not yet wired:
## Harness systemd unit shape
One harness binary (`hive`), one `harness-base.nix` template, one
One harness serve binary (`hive-agent`, with its `hive-agent-mcp` /
`hive-agent-wake` siblings), one `harness-base.nix` template, one
service unit (`systemd.services.hive-ag3nt`) for all agents. There
is no longer a separate manager service name or role distinction in
the harness — privilege differences live server-side in the broker
@ -259,7 +260,8 @@ bit set` regardless of `hyperhive.user.passwordlessSudo`.
### `serviceConfig` highlights
- `ExecStart = pkgs.hyperhive/bin/hive serve` — single binary.
- `ExecStart = pkgs.hyperhive/bin/hive-agent` — same binary for
every agent.
- `Restart = on-failure`, `RestartSec = 2` — keeps the harness
resilient across transient crashes without thundering retries.
- `RuntimeDirectory = "hive-config"``/run/hive-config/` owned by

View file

@ -5,7 +5,8 @@ claude has access to in return.
## The loop
Each agent harness (`hive serve` — one binary for all agents) runs:
Each agent harness (`hive-agent` — one serve-loop binary for all
agents) runs:
1. Long-poll `Recv` on its socket. The host-side broker
(`broker.rs::recv_blocking_batch`) returns immediately if there's
@ -51,38 +52,37 @@ Each agent harness (`hive serve` — one binary for all agents) runs:
## Harness binary shape
One `hive` binary for all agents. The earlier split into
`hive-ag3nt` + `hive-m1nd` was collapsed because the privilege
boundary lives server-side at the broker socket
(`/run/hive/mcp.sock`): `ManagerRequest` calls are refused by the
standard agent socket regardless of who sends them.
Three sibling binaries out of the one `hive-ag3nt` crate, all
role-agnostic. (The earlier split into `hive-ag3nt` + `hive-m1nd`
was collapsed because the privilege boundary lives server-side at
the broker socket (`/run/hive/mcp.sock`): `ManagerRequest` calls are
refused by the standard agent socket regardless of who sends them.)
Three subcommands:
- `serve` — long-running harness loop (the inbox poll +
- `hive-agent` — long-running harness loop (the inbox poll +
claude-pump + ack/requeue cycle described above).
- `mcp` — MCP server. Default: stdio child claude spawns via
`--mcp-config` per turn. With `--http <addr>`, runs as a persistent
streamable-HTTP daemon instead (used by the `hive-mcp-http`
systemd unit when `hyperhive.mcp.httpPort` is set).
- `wake --from <name> --body <body>` — push a message into our own
inbox so the next turn fires with the given body. Used by
co-process daemons (matrix bridge, scraper, webhook listeners)
to nudge claude on external events. `--body -` reads from stdin.
- `hive-agent-mcp` — MCP server. Default: stdio child claude spawns
via `--mcp-config` per turn (the serve loop renders the config to
point at this sibling of its own `/proc/self/exe`). With
`--http <addr>`, runs as a persistent streamable-HTTP daemon
instead (used by the `hive-mcp-http` systemd unit when
`hyperhive.mcp.httpPort` is set).
- `hive-agent-wake --from <name> --body <body>` — push a message into
our own inbox so the next turn fires with the given body. Used by
co-process helpers (scrapers, webhook listeners) to nudge claude on
external events. `--body -` reads from stdin.
### `Surface` trait + zero-sized type tags
`AgentRequest` / `AgentResponse` (= `ManagerRequest` / `ManagerResponse`
type aliases) are the wire types. There is one role: agent.
`bin/hive.rs` factors the turn loop through a `Surface` trait with one
zero-sized impl (`AgentSurface`) wrapping:
`bin/hive-agent.rs` factors the turn loop through a `Surface` trait
with one zero-sized impl (`AgentSurface`) wrapping:
- One async method per wire op: `ack_turn`, `requeue_inflight`,
`inbox_unread`, `post_turn_counts`, `send_to_parent`,
`recv_next`, `wake_external`.
`inbox_unread`, `post_turn_counts`, `send_to_parent`, `recv_next`.
`main()` calls `serve_main::<AgentSurface>` for all roles. The turn
loop (`serve_loop` / `handle_turn` / `wake`) has no per-role branches.
loop (`serve_loop` / `handle_turn`) has no per-role branches.
### Boot wiring

View file

@ -138,7 +138,7 @@ External MCP servers (and any other in-container process) can
inject a wake-up event into the agent's inbox via the per-agent
socket at `/run/hive/mcp.sock`. Two equivalent paths:
- **Shell out to `hive wake --from <label> --body <text>`**
- **Shell out to `hive-agent-wake --from <label> --body <text>`**
(use `--body -` to read body from stdin). Already on the
container's `PATH` since the harness binary is in
`systemPackages`. Convenient for shell-script integrations and