feat(#2659): serve hive-matrix-mcp over persistent streamable-http, drop stdio bridge
This commit is contained in:
parent
ae8d1aaac4
commit
a66b7ab298
21 changed files with 411 additions and 856 deletions
|
|
@ -1,8 +1,9 @@
|
|||
//! Formatting / render helpers for the MCP tool surface: ack / recv /
|
||||
//! loose-end / agent-meta reply shaping plus the retry annotation.
|
||||
//! Stateless string builders, with one exception —
|
||||
//! [`matrix_unread_summary`] queries the local matrix daemon socket
|
||||
//! (best-effort) so `get_loose_ends` can prepend an unread-rooms entry.
|
||||
//! [`matrix_unread_summary`] queries `hive-matrix-daemon`'s local
|
||||
//! `/unread-summary` status endpoint (best-effort) so `get_loose_ends`
|
||||
//! can prepend an unread-rooms entry.
|
||||
|
||||
/// Render the three identical failure arms every data-returning tool handler
|
||||
/// repeats: a broker `Err` → `"{tool} failed: {m}"`, an unexpected `Ok` variant
|
||||
|
|
@ -272,27 +273,30 @@ pub(super) struct MatrixRoomUnread {
|
|||
last_sender: Option<String>,
|
||||
}
|
||||
|
||||
/// Query the local matrix daemon for per-room unread summaries. Returns
|
||||
/// `None` if the daemon socket is absent or the query fails. Best-effort:
|
||||
/// agents without matrix configured are not penalised.
|
||||
/// Default port `hive-matrix-daemon` serves its MCP + status endpoints
|
||||
/// on (`hyperhive.mcp.matrixHttpPort`'s nix default). Overridable via
|
||||
/// `HIVE_MATRIX_HTTP_PORT` for parity with the port options nix already
|
||||
/// exposes; unset in practice since a single fixed port is safe (each
|
||||
/// agent container is its own network namespace — see docs/network.md).
|
||||
const DEFAULT_MATRIX_HTTP_PORT: u16 = 8792;
|
||||
|
||||
/// Short request timeout for the local status query below — this must
|
||||
/// never stall a turn waiting on a wedged same-container daemon.
|
||||
const MATRIX_STATUS_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(2);
|
||||
|
||||
/// Query the local matrix daemon's `/unread-summary` status endpoint
|
||||
/// for per-room unread summaries. Returns `None` if the daemon isn't
|
||||
/// reachable or the query fails. Best-effort: agents without matrix
|
||||
/// configured are not penalised.
|
||||
pub(super) async fn matrix_unread_summary() -> Option<Vec<MatrixRoomUnread>> {
|
||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
|
||||
use tokio::net::UnixStream;
|
||||
let socket = std::env::var_os("HIVE_MATRIX_SOCKET").map_or_else(
|
||||
|| std::path::PathBuf::from("/run/hive-matrix/socket"),
|
||||
std::path::PathBuf::from,
|
||||
);
|
||||
if !socket.exists() {
|
||||
return None;
|
||||
}
|
||||
let mut stream = UnixStream::connect(&socket).await.ok()?;
|
||||
stream
|
||||
.write_all(b"{\"method\":\"unread_summary\"}\n")
|
||||
.await
|
||||
let port = std::env::var("HIVE_MATRIX_HTTP_PORT")
|
||||
.unwrap_or_else(|_| DEFAULT_MATRIX_HTTP_PORT.to_string());
|
||||
let url = format!("http://127.0.0.1:{port}/unread-summary");
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(MATRIX_STATUS_TIMEOUT)
|
||||
.build()
|
||||
.ok()?;
|
||||
let mut lines = BufReader::new(stream).lines();
|
||||
let line = lines.next_line().await.ok()??;
|
||||
let val: serde_json::Value = serde_json::from_str(&line).ok()?;
|
||||
let val: serde_json::Value = client.get(&url).send().await.ok()?.json().await.ok()?;
|
||||
// Response: {"kind":"ok","payload":[{label, count, last_body?, last_sender?}]}
|
||||
let arr = val.get("payload")?.as_array()?;
|
||||
serde_json::from_value(serde_json::Value::Array(arr.clone())).ok()
|
||||
|
|
|
|||
Loading…
Reference in a new issue