Watch
0
0
Fork
You've already forked hyperhive
0

hive-matrix-mcp: retry a secondary account that failed to come up

The daemon's two-minute refresh compared the store's linked account
names with the names it booted with. A secondary that was named but did
not come up - no token at bring-up, a token the homeserver rejected
(M_UNKNOWN_TOKEN), or a homeserver still down after the ~52 s boot
retries - kept its name in the set, so nothing ever noticed it again:
it stayed down until the daemon restarted for some other reason, and
an operator re-linking a rejected account changed no name.

Each such secondary is now tried again on the same two-minute period,
one per tick, after one refresh and then doubling waits capped at
sixteen minutes. One that comes up joins the registry (now behind a
lock) and its sync loop joins the running set; the primary and the
other accounts are not restarted. The store is still only read.

The startup todo wipe moves out of bring_up_account to run once before
any sync loop: run per account, a late secondary would have cleared the
todos the running accounts' sweeps had already deduped.

Part of #5017 (slice M).
This commit is contained in:
atlas 2026-10-13 20:57:12 +02:00 • committed by mara
commit 7f26238c87
7 changed files with 335 additions and 100 deletions

View file

@ -1,7 +1,7 @@
//! MCP tool surface for `hive-matrix-daemon`, served directly over
//! streamable-http — no stdio bridge, no per-turn respawn, no
//! round-trip unix socket. The daemon already owns the account
//! registry in-process (built at startup from the restored matrix-sdk
//! registry in-process (the restored matrix-sdk
//! `Client`s), so each tool call resolves `account` against
//! [`crate::accounts::Registry`] and calls straight into
//! [`crate::handlers`]. Mirrors `hive-bash-mcp::mcp`'s shape (and, one
@ -257,10 +257,8 @@ impl MatrixMcp {
/// account" / "ambiguous, pick one" error the same way a handler
/// error would render (so a bad `account` arg and a bad room/event
/// arg look the same to claude).
fn resolve(&self, account: Option<&str>) -> Result<&matrix_sdk::Client, String> {
self.registry
.resolve(account)
.map(std::convert::AsRef::as_ref)
fn resolve(&self, account: Option<&str>) -> Result<Arc<matrix_sdk::Client>, String> {
self.registry.resolve(account)
}
}
@ -278,7 +276,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::send_message(client, &args.room, &args.body).await)
render(handlers::send_message(&client, &args.room, &args.body).await)
}
#[tool(description = "Open (or reuse) a direct message room with `user_id` \
@ -290,7 +288,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::send_dm(client, &args.user_id, &args.body).await)
render(handlers::send_dm(&client, &args.user_id, &args.body).await)
}
#[tool(
@ -305,7 +303,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::send_file(client, &args.room, &args.path, args.caption.as_deref()).await)
render(handlers::send_file(&client, &args.room, &args.path, args.caption.as_deref()).await)
}
#[tool(description = "Resolve (find-or-create) the DM room with `user_id` \
@ -317,7 +315,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::open_dm(client, &args.user_id).await)
render(handlers::open_dm(&client, &args.user_id).await)
}
#[tool(
@ -330,7 +328,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::send_reaction(client, &args.room, &args.event_id, &args.key).await)
render(handlers::send_reaction(&client, &args.room, &args.event_id, &args.key).await)
}
#[tool(description = "Reply to a specific matrix event in a room, threaded \
@ -342,7 +340,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::send_reply(client, &args.room, &args.event_id, &args.body).await)
render(handlers::send_reply(&client, &args.room, &args.event_id, &args.body).await)
}
#[tool(description = "Mark a specific event as read for this agent. Updates \
@ -353,7 +351,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::mark_read(client, &args.room, &args.event_id).await)
render(handlers::mark_read(&client, &args.room, &args.event_id).await)
}
#[tool(description = "Redact (delete) a specific matrix event in a room — \
@ -366,7 +364,8 @@ impl MatrixMcp {
Err(e) => return format!("matrix error: {e}"),
};
render(
handlers::send_redact(client, &args.room, &args.event_id, args.reason.as_deref()).await,
handlers::send_redact(&client, &args.room, &args.event_id, args.reason.as_deref())
.await,
)
}
@ -379,7 +378,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::list_rooms(client).await)
render(handlers::list_rooms(&client).await)
}
#[tool(
@ -393,7 +392,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::list_invites(client).await)
render(handlers::list_invites(&client).await)
}
#[tool(
@ -408,7 +407,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::join_room(client, &args.room).await)
render(handlers::join_room(&client, &args.room).await)
}
#[tool(
@ -431,7 +430,7 @@ impl MatrixMcp {
);
}
};
render(handlers::resolve_invite(client, &args.room, action).await)
render(handlers::resolve_invite(&client, &args.room, action).await)
}
#[tool(
@ -445,7 +444,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::invite_user(client, &args.room, &args.user_id).await)
render(handlers::invite_user(&client, &args.room, &args.user_id).await)
}
#[tool(
@ -457,7 +456,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::list_room_members(client, &args.room).await)
render(handlers::list_room_members(&client, &args.room).await)
}
#[tool(description = "Read events from a matrix room (default 50, max 200), \
@ -474,7 +473,7 @@ impl MatrixMcp {
Ok(c) => c,
Err(e) => return format!("matrix error: {e}"),
};
render(handlers::read_room(client, &args.room, args.limit, args.from, args.until).await)
render(handlers::read_room(&client, &args.room, args.limit, args.from, args.until).await)
}
#[tool(
@ -491,7 +490,7 @@ impl MatrixMcp {
};
render(
handlers::download_file(
client,
&client,
&args.room,
&args.event_id,
args.dest_path.as_deref(),