Fixes all clippy -D warnings errors in the crates iris owns: hive-sh4re: - doc_lazy_continuation: add blank /// separator in priv_proto.rs - doc_markdown: backtick PRIVATE_NETWORK=0 / PRIVATE_NETWORK=1 hive-matrix-mcp: - map_unwrap_or: map().unwrap_or_else() -> map_or_else() in paths.rs - collapsible_if: if-let chains in wake.rs - doc_markdown: backtick M_UNKNOWN_TOKEN in main.rs - cast_possible_truncation: usize/u64 -> u32::try_from in handlers.rs - map_unwrap_or: map_or_else() in handlers.rs - manual_let_else: match Ok(r) => r, Err => return -> let Ok in handlers.rs - unused_async: remove async from list_invites; update socket.rs call site hive-forge: - doc_markdown: backtick REQUEST_CHANGES / APPROVED / COMMENT in pr_reviews.rs - unnecessary_wraps: list_reviews_text returns () not Result<()> - doc_markdown: backtick start_page / last_page in comments.rs - cast_possible_truncation: PAGE_SIZE u64 -> usize; remove as usize casts hive-ag3nt: - collapsible_if: if-let chains in events.rs and mcp.rs - single_match_else: match -> if let in events.rs and mcp.rs - items_after_statements: hoist STATUS_MAX_CHARS const in mcp.rs - map_unwrap_or: map_or_else() in mcp.rs and mcp_loose_ends.rs - cast_possible_truncation: usize -> u32::try_from in mcp.rs - doc_markdown: backtick snake_case in mcp.rs, needs_update/deployed_sha in web_ui.rs, HISTORY_CAPACITY in web_ui.rs - identical_match_arms: combine manage_root_agent | query_agent_state - redundant_closure: |s| s.to_string() -> ToString::to_string in web_ui.rs - duration_suboptimal_units: from_secs(3600) -> from_hours(1) in turn.rs Remaining failures in hive-c0re (39), hive-priv (8), hive-bash-mcp (11) are owned by damocles.
90 lines
3.1 KiB
Rust
90 lines
3.1 KiB
Rust
//! `hive-matrix-daemon` binary — long-running matrix-sdk Client + sync
|
|
//! loop per agent. Bridges incoming room events to hyperhive wake
|
|
//! signals and serves the unix socket the stdio MCP bridge talks to.
|
|
//!
|
|
//! Lifecycle:
|
|
//! 1. Read access token from `paths::token_file()` (fail clean if absent).
|
|
//! 2. Whoami probe → recover `user_id` + `device_id` → restore
|
|
//! matrix-sdk session (no login flow).
|
|
//! 3. Install the message-event handler that fires hyperhive wakes.
|
|
//! 4. Spawn the unix socket listener for the MCP bridge.
|
|
//! 5. Run sync forever.
|
|
//!
|
|
//! Standalone-degraded boot: missing token file → exit 0 cleanly so
|
|
//! systemd's `ConditionPathExists=` doesn't have to be perfectly
|
|
//! synced with hive-c0re's token-provisioning timing.
|
|
//!
|
|
//! Stale-token recovery: handled in `client::build_and_restore` — see
|
|
//! that module for the `M_UNKNOWN_TOKEN` detection + cleanup flow.
|
|
|
|
use anyhow::{Context, Result};
|
|
use matrix_sdk::config::SyncSettings;
|
|
|
|
mod client;
|
|
mod handlers;
|
|
mod paths;
|
|
mod protocol;
|
|
mod socket;
|
|
mod timeline;
|
|
mod wake;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
tracing_subscriber::fmt()
|
|
.with_env_filter(
|
|
tracing_subscriber::EnvFilter::try_from_default_env()
|
|
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
|
|
)
|
|
.with_writer(std::io::stderr)
|
|
.init();
|
|
|
|
let homeserver = paths::homeserver_url();
|
|
let token_file = paths::token_file();
|
|
let state_dir = paths::matrix_state_dir();
|
|
let mcp_socket = paths::daemon_socket();
|
|
let hyperhive_socket = paths::hyperhive_socket();
|
|
|
|
if !tokio::fs::try_exists(&token_file).await.unwrap_or(false) {
|
|
tracing::warn!(
|
|
path = %token_file.display(),
|
|
"matrix token file absent; exiting cleanly (hive-c0re will provision \
|
|
it on first agent registration, then systemd restarts us)"
|
|
);
|
|
return Ok(());
|
|
}
|
|
|
|
tracing::info!(
|
|
homeserver,
|
|
token_file = %token_file.display(),
|
|
state_dir = %state_dir.display(),
|
|
"hive-matrix-daemon starting"
|
|
);
|
|
|
|
let matrix_client = client::build_and_restore(&homeserver, &token_file, &state_dir)
|
|
.await
|
|
.context("build matrix client")?;
|
|
|
|
timeline::install_message_handler(&matrix_client, hyperhive_socket.clone());
|
|
timeline::install_invite_handler(&matrix_client, hyperhive_socket);
|
|
|
|
// Spawn the unix socket server before sync starts so the MCP
|
|
// bridge can connect as soon as the first claude turn fires. The
|
|
// socket dispatches against the same `Client` we sync on, so any
|
|
// tool call benefits from the sync state-cache.
|
|
let socket_client = matrix_client.clone();
|
|
let socket_listener = mcp_socket.clone();
|
|
tokio::spawn(async move {
|
|
if let Err(e) = socket::serve(&socket_listener, socket_client).await {
|
|
tracing::error!(error = %e, "mcp socket server exited");
|
|
}
|
|
});
|
|
|
|
// Sync forever; matrix-sdk handles reconnection internally.
|
|
let sync_settings = SyncSettings::default();
|
|
matrix_client
|
|
.sync(sync_settings)
|
|
.await
|
|
.context("matrix-sdk sync loop exited")?;
|
|
|
|
Ok(())
|
|
}
|