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:
parent
e149ff3315
commit
23f4f1823b
2 changed files with 77 additions and 505 deletions
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 _;
|
||||
|
|
|
|||
Loading…
Reference in a new issue