feat(c0re): /api/stats-hive — hive-wide turn-stats rollup
#1424 P2 backend. New hive_stats module aggregates every agent's turn-stats.sqlite read-only (reusing Coordinator::kept_state_names + agent_harness_dir, skipping missing/unreadable dbs) into swarm totals, a busiest-first per-agent rollup, swarm model mix, and a labelled USD cost estimate (rough model->price table; can move to a nix option later). Exposed as GET /api/stats-hive?window=. Dashboard UI follows.
This commit is contained in:
parent
07e8f442cb
commit
447a84e8a6
3 changed files with 308 additions and 0 deletions
|
|
@ -67,6 +67,7 @@ pub async fn serve(port: u16, coord: Arc<Coordinator>) -> Result<()> {
|
|||
.route("/api/approval-diff/{id}", get(get_approval_diff))
|
||||
.route("/api/state-file", get(get_state_file))
|
||||
.route("/api/reminders", get(api_reminders))
|
||||
.route("/api/stats-hive", get(api_stats_hive))
|
||||
.route("/api/build-logs", get(get_build_logs_all))
|
||||
.route("/api/build-logs/{agent}", get(get_build_logs_agent))
|
||||
.route("/api/build-logs/id/{id}", get(get_build_log_full))
|
||||
|
|
@ -1734,6 +1735,19 @@ async fn api_reminders(State(state): State<AppState>) -> Response {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct StatsHiveQuery {
|
||||
window: Option<String>,
|
||||
}
|
||||
|
||||
/// 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`.
|
||||
async fn api_stats_hive(axum::extract::Query(q): axum::extract::Query<StatsHiveQuery>) -> Response {
|
||||
let window = crate::hive_stats::Window::parse(q.window.as_deref().unwrap_or("24h"));
|
||||
axum::Json(crate::hive_stats::hive_snapshot(window)).into_response()
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct BuildLogsQuery {
|
||||
/// Maximum number of rows to return. Capped server-side at 50
|
||||
|
|
|
|||
Loading…
Reference in a new issue