matrix: hive-matrix-mcp crate (daemon+stdio bridge) + harness wiring (#548 phase 3)
This commit is contained in:
parent
23ed124881
commit
e6c53045ad
16 changed files with 3310 additions and 35 deletions
|
|
@ -149,6 +149,52 @@
|
|||
'';
|
||||
};
|
||||
|
||||
options.hyperhive.matrix.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Enable per-agent matrix integration via `hive-matrix-mcp`
|
||||
(#548 phase 3). When true (the default), the harness:
|
||||
|
||||
- runs `hive-matrix-daemon` as a systemd unit that holds a
|
||||
matrix-sdk Client + sync against the homeserver at
|
||||
`HIVE_MATRIX_URL` (default `http://localhost:8008` — the
|
||||
in-host tuwunel from `nix/modules/hive-matrix.nix`). The
|
||||
daemon auto-skips when `<state>/matrix-token` is missing,
|
||||
and a `systemd.paths` watcher restarts it the moment
|
||||
hive-c0re provisions the token (mirrors `matrix-avatar-sync`
|
||||
shape from #571).
|
||||
- exposes the matrix tool surface (send_message, send_dm,
|
||||
send_reaction, send_reply, mark_read, list_rooms,
|
||||
list_room_members, read_room) to claude via an auto-injected
|
||||
`extraMcpServers.matrix` entry. Claude spawns the stdio
|
||||
`hive-matrix-mcp` bridge per turn, which forwards each tool
|
||||
call to the daemon over `/run/hive-matrix.sock`.
|
||||
- wakes the agent on incoming room events via a short teaser
|
||||
Wake signal (`[matrix] <sender> in <room>: <first 100c>…`)
|
||||
to the hyperhive control socket; the full event stays
|
||||
unread server-side until `read_room` consumes it.
|
||||
|
||||
Set to `false` for agents that should NOT have matrix tools at
|
||||
all (e.g. agents on a host without `hyperhive.matrix.enable` on
|
||||
the meta side). When token file is absent the daemon and MCP
|
||||
both no-op cleanly anyway, so `false` is rarely necessary.
|
||||
'';
|
||||
};
|
||||
|
||||
options.hyperhive.matrix.url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http://localhost:8008";
|
||||
example = "https://matrix.darkest.space";
|
||||
description = ''
|
||||
Matrix homeserver URL the agent's `hive-matrix-daemon` connects
|
||||
to. Default points at the in-host tuwunel (shared netns).
|
||||
Override per-agent when an agent should talk to an external
|
||||
homeserver instead (e.g. a federation-only setup or a remote
|
||||
hive's tuwunel reached via a vpn).
|
||||
'';
|
||||
};
|
||||
|
||||
options.hyperhive.frontend.dist = lib.mkOption {
|
||||
type = lib.types.package;
|
||||
default = pkgs.hyperhive-frontend;
|
||||
|
|
@ -483,6 +529,19 @@
|
|||
}
|
||||
];
|
||||
|
||||
# Auto-inject the matrix MCP entry when matrix is enabled (#548
|
||||
# phase 3). Operator can override or disable by setting their own
|
||||
# `extraMcpServers.matrix` (nix submodule merge takes the operator's
|
||||
# value) or by flipping `hyperhive.matrix.enable = false`.
|
||||
hyperhive.extraMcpServers = lib.mkIf config.hyperhive.matrix.enable {
|
||||
matrix = lib.mkDefault {
|
||||
command = "${pkgs.hyperhive}/bin/hive-matrix-mcp";
|
||||
args = [ ];
|
||||
env = { };
|
||||
allowedTools = [ "*" ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."hyperhive/extra-mcp.json".text = builtins.toJSON config.hyperhive.extraMcpServers;
|
||||
|
||||
# Operator-set per-agent icon (hyperhive.icon). When configured, the
|
||||
|
|
@ -745,6 +804,48 @@
|
|||
'';
|
||||
};
|
||||
|
||||
# Long-running matrix-sdk Client + sync per agent (#548 phase 3).
|
||||
# Holds the unix socket the stdio `hive-matrix-mcp` bridge talks
|
||||
# to, and emits hyperhive wake signals on incoming room events
|
||||
# via `/run/hive/mcp.sock`. Conditional on `hyperhive.matrix.enable`
|
||||
# AND token-file presence (the daemon binary itself exits 0 on
|
||||
# missing token, but the path watcher below restarts it the
|
||||
# moment the token lands — same first-boot-ordering pattern as
|
||||
# matrix-avatar-sync.path / #571).
|
||||
systemd.services.hive-matrix-daemon = lib.mkIf config.hyperhive.matrix.enable {
|
||||
description = "long-running matrix-sdk Client + MCP daemon socket";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network-online.target" ];
|
||||
wants = [ "network-online.target" ];
|
||||
environment = {
|
||||
HIVE_MATRIX_URL = config.hyperhive.matrix.url;
|
||||
RUST_LOG = "info";
|
||||
};
|
||||
serviceConfig = {
|
||||
ExecStart = "${pkgs.hyperhive}/bin/hive-matrix-daemon";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 5;
|
||||
# /run/hive-matrix.sock + the matrix-sdk-state sqlite dir
|
||||
# don't need a StateDirectory= — the socket is on tmpfs (gone
|
||||
# on restart, which is correct) and the sqlite dir lives in
|
||||
# the bind-mounted agent state, mode-managed by the harness.
|
||||
};
|
||||
};
|
||||
|
||||
# Path-trigger sibling so hive-matrix-daemon fires the moment
|
||||
# `<state>/matrix-token` appears (#548 phase 3, mirrors the
|
||||
# matrix-avatar-sync.path pattern from #571). On clean boot
|
||||
# hive-c0re provisions the token AFTER agent containers come up;
|
||||
# without the trigger the daemon would exit 0 quietly and the
|
||||
# MCP would have no backend until next restart. With the watcher
|
||||
# the daemon comes alive in the same boot cycle as provisioning.
|
||||
systemd.paths.hive-matrix-daemon = lib.mkIf config.hyperhive.matrix.enable {
|
||||
description = "trigger hive-matrix-daemon when matrix-token appears";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
pathConfig.PathExists = "/state/matrix-token";
|
||||
pathConfig.PathExistsGlob = "/agents/*/state/matrix-token";
|
||||
};
|
||||
|
||||
# Path-trigger sibling so matrix-avatar-sync fires the moment
|
||||
# `<state>/matrix-token` appears (#571 closes argus's first-boot
|
||||
# ordering nag on #567). On a clean boot hive-c0re's matrix
|
||||
|
|
|
|||
Loading…
Reference in a new issue