hive-sh4re: split inbox, container, journal, and schedule wire shapes into their own modules
Closes the #3110 split — lib.rs is now just the crate doc comment and the pub mod list. journal.rs's new doc comment fixes a pre-existing bug: the old JournalPriority doc text in lib.rs was actually half Capability's doc (a leftover from an earlier reorder that moved the code but not the comment above it).
This commit is contained in:
parent
b785f96d30
commit
80f16094f1
30 changed files with 513 additions and 486 deletions
|
|
@ -334,7 +334,7 @@ pub struct GetHostJournalArgs {
|
|||
pub lines: Option<u32>,
|
||||
/// Minimum syslog priority level.
|
||||
#[serde(default)]
|
||||
pub priority: Option<hive_sh4re::JournalPriority>,
|
||||
pub priority: Option<hive_sh4re::journal::JournalPriority>,
|
||||
/// Regex to match against log message fields (journalctl --grep).
|
||||
#[serde(default)]
|
||||
pub grep: Option<String>,
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ impl AgentServer {
|
|||
let summary = format_matrix_summary(&unread_rooms);
|
||||
loose_ends.insert(
|
||||
0,
|
||||
hive_sh4re::LooseEnd::UnreadMatrix {
|
||||
hive_sh4re::inbox::LooseEnd::UnreadMatrix {
|
||||
rooms: total,
|
||||
summary,
|
||||
},
|
||||
|
|
@ -507,7 +507,7 @@ impl AgentServer {
|
|||
// Reminders are harness-local — dial the in-agent socket
|
||||
// directly instead of the broker; every other kind
|
||||
// (question/approval) still lives in c0re.
|
||||
if kind == hive_sh4re::CancelLooseEndKind::Reminder {
|
||||
if kind == hive_sh4re::inbox::CancelLooseEndKind::Reminder {
|
||||
return match dial_agent_socket(&hive_agent_sock::Request::CancelReminder { id })
|
||||
.await
|
||||
{
|
||||
|
|
@ -527,7 +527,7 @@ impl AgentServer {
|
|||
let (resp, retries) = self
|
||||
.dispatch(hive_core_agent_sock::Request::CancelLooseEnd { kind, id })
|
||||
.await;
|
||||
if resp.is_ok() && kind == hive_sh4re::CancelLooseEndKind::Question {
|
||||
if resp.is_ok() && kind == hive_sh4re::inbox::CancelLooseEndKind::Question {
|
||||
// Best-effort — cancel is ownership-gated to the asker on
|
||||
// the c0re side, so a successful cancel here always means
|
||||
// *this* agent's own `asked` mirror row for `id`. Known gap
|
||||
|
|
@ -627,8 +627,8 @@ impl AgentServer {
|
|||
`at_unix_timestamp`"
|
||||
.to_string();
|
||||
}
|
||||
(Some(s), None) => hive_sh4re::ReminderTiming::InSeconds { seconds: s },
|
||||
(None, Some(t)) => hive_sh4re::ReminderTiming::At { unix_timestamp: t },
|
||||
(Some(s), None) => hive_sh4re::inbox::ReminderTiming::InSeconds { seconds: s },
|
||||
(None, Some(t)) => hive_sh4re::inbox::ReminderTiming::At { unix_timestamp: t },
|
||||
};
|
||||
// Reminders are harness-local — dial the in-agent socket
|
||||
// directly instead of the broker.
|
||||
|
|
|
|||
|
|
@ -66,8 +66,8 @@ pub fn format_recv(resp: Result<hive_core_agent_sock::Response, anyhow::Error>)
|
|||
|
||||
/// The synthetic single-message directive rendered for a fenced (graceful-stop)
|
||||
/// inbox — see the `GracefulStop` arm of [`format_recv`].
|
||||
fn graceful_stop_message() -> hive_sh4re::DeliveredMessage {
|
||||
hive_sh4re::DeliveredMessage {
|
||||
fn graceful_stop_message() -> hive_sh4re::inbox::DeliveredMessage {
|
||||
hive_sh4re::inbox::DeliveredMessage {
|
||||
from: "graceful-stop".into(),
|
||||
body: "⛔ GRACEFUL STOP IN PROGRESS — the container shuts down as soon as this turn \
|
||||
ends. Flush anything worth keeping to your durable /state files, then END \
|
||||
|
|
@ -85,7 +85,10 @@ fn graceful_stop_message() -> hive_sh4re::DeliveredMessage {
|
|||
/// depth; when non-zero a shared "(N more pending …)" hint (identical to the
|
||||
/// wake prompt's) is appended so an in-turn drain knows more is queued. The
|
||||
/// empty path never carries the hint (nothing was popped).
|
||||
fn render_recv_messages(messages: &[hive_sh4re::DeliveredMessage], remaining: u64) -> String {
|
||||
fn render_recv_messages(
|
||||
messages: &[hive_sh4re::inbox::DeliveredMessage],
|
||||
remaining: u64,
|
||||
) -> String {
|
||||
use std::fmt::Write as _;
|
||||
if messages.is_empty() {
|
||||
return "(empty)".to_owned();
|
||||
|
|
@ -93,7 +96,7 @@ fn render_recv_messages(messages: &[hive_sh4re::DeliveredMessage], remaining: u6
|
|||
let mut out = if messages.len() == 1 {
|
||||
let m = &messages[0];
|
||||
let banner = if m.redelivered {
|
||||
hive_sh4re::REDELIVERY_HINT
|
||||
hive_sh4re::inbox::REDELIVERY_HINT
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
|
@ -106,7 +109,7 @@ fn render_recv_messages(messages: &[hive_sh4re::DeliveredMessage], remaining: u6
|
|||
out.push_str("\n---\n\n");
|
||||
}
|
||||
let banner = if m.redelivered {
|
||||
hive_sh4re::REDELIVERY_HINT
|
||||
hive_sh4re::inbox::REDELIVERY_HINT
|
||||
} else {
|
||||
""
|
||||
};
|
||||
|
|
@ -120,7 +123,7 @@ fn render_recv_messages(messages: &[hive_sh4re::DeliveredMessage], remaining: u6
|
|||
}
|
||||
out
|
||||
};
|
||||
out.push_str(&hive_sh4re::pending_hint(remaining));
|
||||
out.push_str(&hive_sh4re::inbox::pending_hint(remaining));
|
||||
out
|
||||
}
|
||||
|
||||
|
|
@ -156,14 +159,14 @@ fn msg_id_tag(id: i64) -> String {
|
|||
/// inbox messages are).
|
||||
const MAX_RENDERED_TODOS: usize = 40;
|
||||
|
||||
/// Render one non-`Todo` [`hive_sh4re::LooseEnd`] variant onto `out`. Split
|
||||
/// Render one non-`Todo` [`hive_sh4re::inbox::LooseEnd`] variant onto `out`. Split
|
||||
/// out of `render_loose_ends` to keep that function under clippy's
|
||||
/// `too_many_lines` limit — `Todo` stays inline there since it also needs
|
||||
/// the shared `shown_todos` counter.
|
||||
fn render_one_loose_end(out: &mut String, t: &hive_sh4re::LooseEnd) {
|
||||
fn render_one_loose_end(out: &mut String, t: &hive_sh4re::inbox::LooseEnd) {
|
||||
use std::fmt::Write as _;
|
||||
match t {
|
||||
hive_sh4re::LooseEnd::Approval {
|
||||
hive_sh4re::inbox::LooseEnd::Approval {
|
||||
id,
|
||||
agent,
|
||||
commit_ref,
|
||||
|
|
@ -179,7 +182,7 @@ fn render_one_loose_end(out: &mut String, t: &hive_sh4re::LooseEnd) {
|
|||
"- approval #{id} ({agent} @ {commit_ref}, {age_seconds}s old){desc}"
|
||||
);
|
||||
}
|
||||
hive_sh4re::LooseEnd::Question {
|
||||
hive_sh4re::inbox::LooseEnd::Question {
|
||||
id,
|
||||
asker,
|
||||
target,
|
||||
|
|
@ -192,7 +195,7 @@ fn render_one_loose_end(out: &mut String, t: &hive_sh4re::LooseEnd) {
|
|||
"- question #{id} ({asker} → {to}, {age_seconds}s old): {question}"
|
||||
);
|
||||
}
|
||||
hive_sh4re::LooseEnd::Reminder {
|
||||
hive_sh4re::inbox::LooseEnd::Reminder {
|
||||
id,
|
||||
owner,
|
||||
message,
|
||||
|
|
@ -204,13 +207,13 @@ fn render_one_loose_end(out: &mut String, t: &hive_sh4re::LooseEnd) {
|
|||
"- reminder #{id} ({owner}, scheduled {age_seconds}s ago, due_at={due_at}): {message}"
|
||||
);
|
||||
}
|
||||
hive_sh4re::LooseEnd::PendingMessages { count } => {
|
||||
hive_sh4re::inbox::LooseEnd::PendingMessages { count } => {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"- {count} pending inbox message(s) — drain with recv (recv(max: {count}) to batch)"
|
||||
);
|
||||
}
|
||||
hive_sh4re::LooseEnd::UnreadMatrix { rooms, summary } => {
|
||||
hive_sh4re::inbox::LooseEnd::UnreadMatrix { rooms, summary } => {
|
||||
let _ = write!(out, "- unread matrix messages in {rooms} room(s)");
|
||||
if summary.is_empty() {
|
||||
let _ = writeln!(
|
||||
|
|
@ -228,13 +231,13 @@ fn render_one_loose_end(out: &mut String, t: &hive_sh4re::LooseEnd) {
|
|||
);
|
||||
}
|
||||
}
|
||||
hive_sh4re::LooseEnd::Todo { .. } => {
|
||||
hive_sh4re::inbox::LooseEnd::Todo { .. } => {
|
||||
// Handled inline by the caller (needs the shared shown-count).
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Render one `Todo` [`hive_sh4re::LooseEnd`] onto `out`. Split out for the
|
||||
/// Render one `Todo` [`hive_sh4re::inbox::LooseEnd`] onto `out`. Split out for the
|
||||
/// same `too_many_lines` reason as [`render_one_loose_end`].
|
||||
fn render_todo_loose_end(
|
||||
out: &mut String,
|
||||
|
|
@ -258,7 +261,7 @@ fn render_todo_loose_end(
|
|||
/// Inner renderer for a `Vec<LooseEnd>` already extracted from the socket
|
||||
/// reply. Called by the `get_loose_ends` handler, which injects the
|
||||
/// `UnreadMatrix` entry before formatting.
|
||||
pub(super) fn render_loose_ends(loose_ends: &[hive_sh4re::LooseEnd]) -> String {
|
||||
pub(super) fn render_loose_ends(loose_ends: &[hive_sh4re::inbox::LooseEnd]) -> String {
|
||||
use std::fmt::Write as _;
|
||||
if loose_ends.is_empty() {
|
||||
return "(no loose ends)".to_owned();
|
||||
|
|
@ -267,7 +270,7 @@ pub(super) fn render_loose_ends(loose_ends: &[hive_sh4re::LooseEnd]) -> String {
|
|||
let mut shown_todos = 0usize;
|
||||
let mut hidden_todos = 0usize;
|
||||
for t in loose_ends {
|
||||
let hive_sh4re::LooseEnd::Todo {
|
||||
let hive_sh4re::inbox::LooseEnd::Todo {
|
||||
id,
|
||||
subsystem,
|
||||
subsystem_key,
|
||||
|
|
@ -376,7 +379,7 @@ pub(super) async fn dial_agent_socket(
|
|||
/// (loose-ends v2). Returns `None` when `HIVE_AGENT_SOCKET` is unset /
|
||||
/// absent or the query fails — best-effort, like [`matrix_unread_summary`],
|
||||
/// so an agent without the socket is not penalised.
|
||||
pub(super) async fn local_todos() -> Option<Vec<hive_sh4re::LooseEnd>> {
|
||||
pub(super) async fn local_todos() -> Option<Vec<hive_sh4re::inbox::LooseEnd>> {
|
||||
match dial_agent_socket(&hive_agent_sock::Request::ListTodos { subsystem: None }).await? {
|
||||
hive_agent_sock::Response::LooseEnds { loose_ends } => Some(loose_ends),
|
||||
_ => None,
|
||||
|
|
@ -386,7 +389,7 @@ pub(super) async fn local_todos() -> Option<Vec<hive_sh4re::LooseEnd>> {
|
|||
/// Query the harness's in-agent socket for this agent's local pending
|
||||
/// reminders — was a broker query before reminders moved in-container.
|
||||
/// Same best-effort contract as [`local_todos`].
|
||||
pub(super) async fn local_reminders() -> Option<Vec<hive_sh4re::LooseEnd>> {
|
||||
pub(super) async fn local_reminders() -> Option<Vec<hive_sh4re::inbox::LooseEnd>> {
|
||||
match dial_agent_socket(&hive_agent_sock::Request::ListReminders).await? {
|
||||
hive_agent_sock::Response::LooseEnds { loose_ends } => Some(loose_ends),
|
||||
_ => None,
|
||||
|
|
@ -397,7 +400,7 @@ pub(super) async fn local_reminders() -> Option<Vec<hive_sh4re::LooseEnd>> {
|
|||
/// (both roles — asked and answering). Same best-effort
|
||||
/// contract as [`local_reminders`]; c0re stays the actual `Ask`/`Answer`
|
||||
/// routing, this only mirrors the durable "still owed a reply" view.
|
||||
pub(super) async fn local_questions() -> Option<Vec<hive_sh4re::LooseEnd>> {
|
||||
pub(super) async fn local_questions() -> Option<Vec<hive_sh4re::inbox::LooseEnd>> {
|
||||
match dial_agent_socket(&hive_agent_sock::Request::ListQuestions).await? {
|
||||
hive_agent_sock::Response::LooseEnds { loose_ends } => Some(loose_ends),
|
||||
_ => None,
|
||||
|
|
@ -451,11 +454,13 @@ pub(super) fn format_matrix_summary(rooms: &[MatrixRoomUnread]) -> String {
|
|||
/// wire enum. Accepts a small alias set so claude doesn't have to
|
||||
/// remember the exact spelling (`"q"` / `"r"` shorthand falls out
|
||||
/// for free).
|
||||
pub(super) fn parse_loose_end_kind(raw: &str) -> Result<hive_sh4re::CancelLooseEndKind, String> {
|
||||
pub(super) fn parse_loose_end_kind(
|
||||
raw: &str,
|
||||
) -> Result<hive_sh4re::inbox::CancelLooseEndKind, String> {
|
||||
match raw.trim().to_ascii_lowercase().as_str() {
|
||||
"question" | "q" => Ok(hive_sh4re::CancelLooseEndKind::Question),
|
||||
"reminder" | "r" => Ok(hive_sh4re::CancelLooseEndKind::Reminder),
|
||||
"approval" | "a" => Ok(hive_sh4re::CancelLooseEndKind::Approval),
|
||||
"question" | "q" => Ok(hive_sh4re::inbox::CancelLooseEndKind::Question),
|
||||
"reminder" | "r" => Ok(hive_sh4re::inbox::CancelLooseEndKind::Reminder),
|
||||
"approval" | "a" => Ok(hive_sh4re::inbox::CancelLooseEndKind::Approval),
|
||||
other => Err(format!(
|
||||
"cancel_loose_end: unknown kind '{other}' \
|
||||
(expected \"question\", \"reminder\", \"approval\", or \"todo\")"
|
||||
|
|
@ -467,11 +472,11 @@ pub(super) fn parse_loose_end_kind(raw: &str) -> Result<hive_sh4re::CancelLooseE
|
|||
/// the success ack so the caller always sees `"question"` /
|
||||
/// `"reminder"` instead of whatever alias they passed in (`"q"` /
|
||||
/// `"r"`).
|
||||
pub(super) fn loose_end_kind_label(kind: hive_sh4re::CancelLooseEndKind) -> &'static str {
|
||||
pub(super) fn loose_end_kind_label(kind: hive_sh4re::inbox::CancelLooseEndKind) -> &'static str {
|
||||
match kind {
|
||||
hive_sh4re::CancelLooseEndKind::Question => "question",
|
||||
hive_sh4re::CancelLooseEndKind::Reminder => "reminder",
|
||||
hive_sh4re::CancelLooseEndKind::Approval => "approval",
|
||||
hive_sh4re::inbox::CancelLooseEndKind::Question => "question",
|
||||
hive_sh4re::inbox::CancelLooseEndKind::Reminder => "reminder",
|
||||
hive_sh4re::inbox::CancelLooseEndKind::Approval => "approval",
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -595,8 +600,8 @@ pub fn annotate_retries(mut s: String, retries: u32) -> String {
|
|||
mod tests {
|
||||
use super::format_recv;
|
||||
|
||||
fn msg(id: i64, from: &str, body: &str) -> hive_sh4re::DeliveredMessage {
|
||||
hive_sh4re::DeliveredMessage {
|
||||
fn msg(id: i64, from: &str, body: &str) -> hive_sh4re::inbox::DeliveredMessage {
|
||||
hive_sh4re::inbox::DeliveredMessage {
|
||||
from: from.to_owned(),
|
||||
body: body.to_owned(),
|
||||
id,
|
||||
|
|
@ -643,7 +648,7 @@ mod tests {
|
|||
assert!(out.starts_with("popped 2 message(s):"));
|
||||
assert_eq!(out.matches("more message(s) pending").count(), 1);
|
||||
// `max` suggestion is clamped to the server-side recv cap.
|
||||
let batch = 9u64.min(u64::from(hive_sh4re::RECV_BATCH_MAX));
|
||||
let batch = 9u64.min(u64::from(hive_sh4re::inbox::RECV_BATCH_MAX));
|
||||
assert!(out.contains(&format!("max: {batch}")));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue