agent page: inbox view of last 30 messages addressed to this agent

new wire request AgentRequest::Recent { limit } / ManagerRequest::Recent
(plus matching responses with Vec<InboxRow>). InboxRow moved to
hive-sh4re so it lives on both surfaces without an internal-to-wire
conversion. host-side dispatch in agent_server / manager_server
calls broker.recent_for(name, limit).

per-agent web_ui /api/state grew an inbox: Vec<InboxRow> populated
via the same per-agent socket (best-effort; transport failure
returns empty). frontend renders as a collapsible <details> section
between the state row and the terminal — fmt timestamp / from /
body in a tight grid, capped at 16em scrollable. only visible when
there are rows.
This commit is contained in:
müde 2026-05-15 20:32:19 +02:00
parent bd7d2d4860
commit 538e0446d7
13 changed files with 151 additions and 20 deletions

View file

@ -6,7 +6,7 @@ use std::sync::Mutex;
use std::time::{SystemTime, UNIX_EPOCH};
use anyhow::{Context, Result};
use hive_sh4re::Message;
use hive_sh4re::{InboxRow, Message};
use rusqlite::{Connection, OptionalExtension, params};
use serde::Serialize;
use tokio::sync::broadcast;
@ -28,16 +28,6 @@ CREATE INDEX IF NOT EXISTS idx_messages_undelivered
/// may drop events past this; we send a `lagged` notice in their stream.
const EVENT_CHANNEL: usize = 256;
/// One row in a `recent_for()` query — the broker's flat view of a
/// message addressed to a given recipient.
#[derive(Debug, Clone, Serialize)]
pub struct InboxRow {
pub id: i64,
pub from: String,
pub body: String,
pub at: i64,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "snake_case", tag = "kind")]
pub enum MessageEvent {