Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/hive-agent/src/web_ui/stats.rs
atlas 58ef299c3c hive-c0re: remove the approvals subsystem
Nothing submits an approval since scheduled prompts left hive-c0re, so the
queue only acted on rows written before that.

- hive-c0re: the approvals store and its migrations, approve/deny/
  resolve actions, the ResolveApproval tail node (and meta_update's
  approval_id), POST /api/approve and /api/deny, the approval views on
  /api/state, the approval_resolved dashboard event, the orphan GC,
  destroy/purge failing pending rows, and the approval rows in
  get_loose_ends. DestroyBookkeeping loses the purge flag, which only
  worded the approval-failure note.
- The CancelLooseEnd request goes: its only hive-c0re arm was the
  approval one. cancel_loose_end handles reminder and todo in the harness.
- Wire types: hive_sh4re::approvals (ReminderStats moves to inbox),
  LooseEnd::Approval, CancelLooseEndKind, HelperEvent::ApprovalResolved,
  ToolGroup::Approvals, HostRequest::{Pending,Approve,Deny} and
  HostResponse.approvals. HOST_SOCK_VERSION goes to 2 for the removed
  field.
- hivectl loses the approvals verbs; docs/tools/hivectl-cli.md is
  regenerated.
- The system prompt drops approval_resolved.
- The approvals table stays in broker.sqlite, unread, the same way the
  operator_questions table was left when its store was removed.
- An `approvals` entry still in tool-groups.json is skipped with a warning
  by ToolGroup::parse_list, like any unknown group.
- docs/agent-lifecycle/approvals.md is renamed to config-changes.md so the
  code's doc pointers resolve; its content follows in the docs commit.
2026-10-04 23:55:32 +02:00

63 lines
2.3 KiB
Rust

//! Stats + loose-ends + todos read endpoints.
use axum::extract::State;
use axum::response::{IntoResponse, Response};
use serde::{Deserialize, Serialize};
use super::AppState;
#[derive(Deserialize)]
pub(super) struct StatsQuery {
window: Option<String>,
}
pub(super) async fn api_stats(
State(_state): State<AppState>,
axum::extract::Query(q): axum::extract::Query<StatsQuery>,
) -> axum::Json<crate::stats::Snapshot> {
let window = crate::stats::Window::parse(q.window.as_deref().unwrap_or("24h"));
let mut snapshot = crate::stats::snapshot_default(window);
// Pass the window span so the local reminder rollup filters its counts
// to the same time range as the chart data.
let window_secs = window.span_secs();
let window_secs_u = u64::try_from(window_secs).unwrap_or(0);
snapshot.reminder_stats = fetch_reminder_stats(window_secs_u).await;
axum::Json(snapshot)
}
/// Fetch reminder activity stats from the harness-local reminder store over
/// `HIVE_AGENT_SOCKET` — was a broker RPC before reminders moved
/// in-container. Returns `None` on any transport / decode failure or
/// when the socket is unset — the stats are decorative, not authoritative.
async fn fetch_reminder_stats(window_secs: u64) -> Option<hive_sh4re::inbox::ReminderStats> {
match crate::todo_server::dial(&hive_agent_sock::Request::ReminderRollup {
since_secs: window_secs,
})
.await?
{
hive_agent_sock::Response::ReminderRollup { stats } => Some(stats),
_ => None,
}
}
#[derive(Serialize)]
struct TodosBody {
todos: Vec<hive_sh4re::inbox::LooseEnd>,
}
/// `GET /api/todos` — snapshot of this agent's local todos (loose-ends v2).
///
/// Connects to the in-agent harness socket (`HIVE_AGENT_SOCKET`) and calls
/// `ListTodos`. Returns `{ "todos": [...] }` where each entry is a
/// `LooseEnd::Todo` (subsystem, key, summary, source, `age_seconds`). Returns
/// an empty array when the socket is unavailable — best-effort, silent failure.
pub(super) async fn api_todos() -> Response {
let todos =
match crate::todo_server::dial(&hive_agent_sock::Request::ListTodos { subsystem: None })
.await
{
Some(hive_agent_sock::Response::LooseEnds { loose_ends }) => loose_ends,
_ => Vec::new(),
};
axum::Json(TodosBody { todos }).into_response()
}