hive-c0re: annotate remaining dashboard routes with utoipa
This commit is contained in:
parent
8ebefeb0d5
commit
582ebe5eee
21 changed files with 738 additions and 45 deletions
|
|
@ -9,8 +9,11 @@ use axum::{
|
|||
response::{IntoResponse, Response},
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use super::{AppState, Ident, error_response, scan_validated_paths};
|
||||
use crate::container_stats::ContainerResource;
|
||||
use crate::hive_stats::HiveStats;
|
||||
|
||||
/// Unread operator-directed messages for the dashboard's Y3R C4LL inbox.
|
||||
/// Returns messages addressed to `"operator"` that haven't been
|
||||
|
|
@ -19,6 +22,15 @@ use super::{AppState, Ident, error_response, scan_validated_paths};
|
|||
/// tokens are validated so the client renders file links like the
|
||||
/// terminal does. Shape: `{ "messages": [{ id, from, body, at,
|
||||
/// in_reply_to, file_refs }] }`.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/operator-inbox",
|
||||
responses(
|
||||
(status = 200, description = "unread operator-directed messages", body = serde_json::Value),
|
||||
(status = 500, description = "broker read failed"),
|
||||
),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn api_operator_inbox(State(state): State<AppState>) -> Response {
|
||||
const INBOX_LIMIT: u64 = 100;
|
||||
match state
|
||||
|
|
@ -58,7 +70,7 @@ pub(super) async fn api_operator_inbox(State(state): State<AppState>) -> Respons
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, IntoParams)]
|
||||
pub(super) struct StatsHiveQuery {
|
||||
window: Option<String>,
|
||||
}
|
||||
|
|
@ -66,6 +78,13 @@ pub(super) struct StatsHiveQuery {
|
|||
/// Hive-wide turn-stats rollup for the dashboard swarm-stats view.
|
||||
/// Aggregates every agent's `hyperhive-turn-stats.sqlite` read-only
|
||||
/// (skips missing/unreadable ones). Window defaults to `24h`.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/stats-hive",
|
||||
params(StatsHiveQuery),
|
||||
responses((status = 200, description = "hive-wide turn-stats rollup", body = HiveStats)),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn api_stats_hive(
|
||||
State(state): State<AppState>,
|
||||
axum::extract::Query(q): axum::extract::Query<StatsHiveQuery>,
|
||||
|
|
@ -80,6 +99,12 @@ pub(super) async fn api_stats_hive(
|
|||
|
||||
/// Live per-agent-container CPU + memory load from cgroup v2. Samples
|
||||
/// CPU over a short interval (~200 ms), so this call briefly awaits.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/container-resources",
|
||||
responses((status = 200, description = "live per-container CPU + memory load", body = Vec<ContainerResource>)),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn api_container_resources() -> Response {
|
||||
axum::Json(crate::container_stats::gather().await).into_response()
|
||||
}
|
||||
|
|
@ -90,6 +115,15 @@ pub(super) async fn api_container_resources() -> Response {
|
|||
/// `{ "entries": [AuditEntry…], "total": N }` so the UI can show
|
||||
/// "latest 500 of N" rather than silently capping. `ts_unix` is in
|
||||
/// **seconds**.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/api/audit-log",
|
||||
responses(
|
||||
(status = 200, description = "recent audit entries + total count", body = serde_json::Value),
|
||||
(status = 500, description = "sqlite read failed"),
|
||||
),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn api_audit_log(State(state): State<AppState>) -> Response {
|
||||
const LIMIT: usize = 500;
|
||||
let entries = match state.coord.audit_log.list_recent(LIMIT) {
|
||||
|
|
@ -109,6 +143,17 @@ pub(super) async fn api_audit_log(State(state): State<AppState>) -> Response {
|
|||
/// rows so vacuum can collect them). Returns `{ "marked": N }` so the
|
||||
/// frontend can show "cleared N messages" feedback without an extra
|
||||
/// fetch.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/agent/{name}/mark-all-read",
|
||||
params(("name" = String, Path, description = "agent name")),
|
||||
responses(
|
||||
(status = 200, description = "count of messages marked read", body = serde_json::Value),
|
||||
(status = 400, description = "bad agent name"),
|
||||
(status = 500, description = "broker write failed"),
|
||||
),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn post_mark_all_read(
|
||||
State(state): State<AppState>,
|
||||
AxumPath(name): AxumPath<String>,
|
||||
|
|
@ -135,12 +180,24 @@ pub(super) async fn post_mark_all_read(
|
|||
/// validation that `to` resolves to a known agent — broker accepts
|
||||
/// arbitrary recipients (and the agent's inbox grows whether or not
|
||||
/// they exist, which is fine for spawn-then-greet flows).
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub(super) struct OpSendForm {
|
||||
to: String,
|
||||
body: String,
|
||||
}
|
||||
|
||||
/// `POST /api/op-send` — operator compose: drop a message into the
|
||||
/// broker addressed to `to` (or `*` to broadcast).
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/op-send",
|
||||
request_body(content = OpSendForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "message sent", body = String),
|
||||
(status = 500, description = "missing to/body, or the broker send failed"),
|
||||
),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn post_op_send(
|
||||
State(state): State<AppState>,
|
||||
Form(form): Form<OpSendForm>,
|
||||
|
|
@ -180,11 +237,22 @@ pub(super) async fn post_op_send(
|
|||
(axum::http::StatusCode::OK, "ok").into_response()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub(super) struct RequestSpawnForm {
|
||||
name: String,
|
||||
}
|
||||
|
||||
/// `POST /api/request-spawn` — queue a spawn approval for `name`.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/api/request-spawn",
|
||||
request_body(content = RequestSpawnForm, content_type = "application/x-www-form-urlencoded"),
|
||||
responses(
|
||||
(status = 200, description = "spawn approval queued", body = String),
|
||||
(status = 500, description = "missing name, or the approval submit failed"),
|
||||
),
|
||||
tag = "misc_api"
|
||||
)]
|
||||
pub(super) async fn post_request_spawn(
|
||||
State(state): State<AppState>,
|
||||
Form(form): Form<RequestSpawnForm>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue