Watch
0
0
Fork
You've already forked hyperhive
0

hive-agent: the per-agent page has no message box; its send route and the broker's operator message are removed

The page's composer (its input, slash commands and completion), POST /send in
hive-agent, the OperatorMsg request of the agent socket and its handler in
hive-c0re, and the broker-error helper only the send route used are deleted:
writing to an agent is the swarm UI's terminal. cancel turn, new session and
log out stay in the state badge's menu; POST /api/compact stays, with nothing
on the page calling it. The request-line limit keeps its size, and its comment
says it is a generous bound now. The docs describe the actions in place of the
footer and the prompt.
This commit is contained in:
iris 2026-11-06 01:07:57 +01:00
commit 23f4f1823b
2 changed files with 77 additions and 505 deletions

View file

@ -1,5 +1,4 @@
//! Operator action POST handlers (send, cancel, compact, reset, todos
//! mark-done).
//! Operator action POST handlers (cancel, compact, reset, todos mark-done).
use axum::{
Form,
@ -12,46 +11,6 @@ use std::future::Future;
use super::{AppState, error_response};
#[derive(Deserialize)]
pub(super) struct SendForm {
body: String,
}
pub(super) async fn post_send(
State(state): State<AppState>,
Form(form): Form<SendForm>,
) -> Response {
let body = form.body.trim().to_owned();
if body.is_empty() {
return error_response(StatusCode::BAD_REQUEST, "send: `body` required");
}
match super::broker_request(
&state.socket,
&hive_core_agent_sock::Request::OperatorMsg { body },
)
.await
{
// 200 instead of 303 → the client doesn't refetch /api/state.
// The operator message becomes a broker `Sent` (already shown
// server-side in the dashboard); on the agent side, the
// resulting `TurnStart` SSE event drives the terminal + the
// inbox row gets consumed by the time `TurnEnd` fires the
// existing turn-end refresh.
Ok(hive_core_agent_sock::Response::Ok) => {
(axum::http::StatusCode::OK, "ok").into_response()
}
Ok(hive_core_agent_sock::Response::Err { message }) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
&format!("send failed: {message}"),
),
Ok(other) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
&format!("send failed: unexpected response: {other:?}"),
),
Err(e) => super::broker_error_response(&e, "send"),
}
}
pub(super) async fn post_cancel_turn(State(state): State<AppState>) -> Response {
super::cancel_turn(&state.bus, &state.interrupted, "operator: /cancel");
(axum::http::StatusCode::OK, "ok").into_response()

View file

@ -1,7 +1,7 @@
//! Per-container HTTP UI. SPA shape: `GET /` returns a static shell;
//! `GET /static/*` serves CSS + JS; `GET /api/state` returns the page
//! state as JSON; the JS app renders. Live events stream on
//! `/events/stream`. Action POSTs (`/send`, `/login/*`) return either a
//! `/events/stream`. Action POSTs (`/login/*`) return either a
//! 303 Redirect (for browsers that submit the form normally) or just
//! 200 OK — the JS app re-fetches `/api/state` afterwards.
//!
@ -76,7 +76,6 @@ fn routes() -> Router<AppState> {
.route("/api/dashboard-state", get(state::api_dashboard_state))
.route("/events/stream", get(stream::events_stream))
.route("/events/history", get(stream::events_history))
.route("/send", post(actions::post_send))
.route("/login/start", post(auth::post_login_start))
.route("/login/code", post(auth::post_login_code))
.route("/login/cancel", post(auth::post_login_cancel))
@ -418,14 +417,14 @@ fn error_response(status: StatusCode, message: &str) -> Response {
}
/// Why a deadline-bounded broker request via the per-agent socket didn't
/// yield a response. Kept distinct so action handlers pick the right status
/// code (see [`broker_error_response`]) while decorative fetches `.ok()` both.
/// yield a response. Callers `.ok()` both today; the variants stay distinct so a
/// handler that must tell a busy hive-c0re from a broken socket can.
enum BrokerError {
/// Outran [`SOCKET_FETCH_TIMEOUT`] — hive-c0re is busy or stalled. A
/// retryable state conflict (→ 409), not a server fault.
/// Outran [`SOCKET_FETCH_TIMEOUT`] — hive-c0re is busy or stalled, not a
/// broken socket.
Timeout,
/// The socket transport itself failed (connect / encode / decode).
Transport(anyhow::Error),
Transport,
}
/// Issue a broker request over the per-agent socket, bounded by
@ -449,27 +448,11 @@ async fn broker_request(
.await
{
Ok(Ok(resp)) => Ok(resp),
Ok(Err(e)) => Err(BrokerError::Transport(e)),
Ok(Err(_)) => Err(BrokerError::Transport),
Err(_) => Err(BrokerError::Timeout),
}
}
/// Map a [`BrokerError`] to an operator-facing error response: a timeout is a
/// retryable "busy" conflict (409), a transport failure is a 500. `action`
/// prefixes the message (e.g. `"send"`, `"get_loose_ends"`).
fn broker_error_response(err: &BrokerError, action: &str) -> Response {
match err {
BrokerError::Timeout => error_response(
StatusCode::CONFLICT,
&format!("{action}: timed out — hive-c0re busy, retry"),
),
BrokerError::Transport(e) => error_response(
StatusCode::INTERNAL_SERVER_ERROR,
&format!("{action}: transport: {e:#}"),
),
}
}
#[cfg(test)]
mod tests {
use std::os::unix::process::CommandExt as _;