api: wire up real agent channel for HUD commands, add connected_viewers to health

This commit is contained in:
Butterfly Dev 2026-04-07 03:58:33 +00:00
parent 2344060d73
commit 4bc5e099cc
3 changed files with 27 additions and 27 deletions

View File

@ -6,15 +6,16 @@ use crate::state::AppState;
/// `GET /api/health`
///
/// Returns server uptime, active sessions, connected agents and version.
/// Returns server uptime, active sessions, connected agents, connected viewers, and version.
pub async fn health(state: web::Data<Arc<AppState>>) -> HttpResponse {
let uptime = state.started_at.elapsed().as_secs();
let (sessions, agents) = state.stats();
let (active_sessions, connected_agents, connected_viewers) = state.stats();
let info = HealthInfo {
status: "ok".into(),
uptime_secs: uptime,
active_sessions: sessions,
connected_agents: agents,
active_sessions,
connected_agents,
connected_viewers,
version: env!("CARGO_PKG_VERSION").into(),
};
HttpResponse::Ok().json(ApiResponse::ok(info))

View File

@ -2,7 +2,7 @@ use actix_web::{web, HttpResponse};
use serde::Deserialize;
use std::sync::Arc;
use crate::models::{ApiResponse, Session};
use crate::models::{ApiResponse, Session, WsMessage};
use crate::state::AppState;
/// `GET /api/sessions` — list every session.
@ -54,8 +54,8 @@ pub struct HudCommandPayload {
/// `POST /api/sessions/{id}/hud` — send a HUD command to the agent for a session.
///
/// The command is forwarded to the connected agent via the session's agent
/// channel (stored in AppState). If no agent is connected, returns 409.
/// Forwards the command through the agent's mpsc channel so it reaches the
/// agent's WebSocket connection in real time.
pub async fn send_hud_command(
state: web::Data<Arc<AppState>>,
path: web::Path<String>,
@ -63,26 +63,24 @@ pub async fn send_hud_command(
) -> HttpResponse {
let session_id = path.into_inner();
// Find the first agent registered for this session.
let agent_id = state
.agents
.iter()
.find(|r| r.session_id == session_id)
.map(|r| r.agent_id.clone());
match agent_id {
Some(aid) => {
// TODO: in the WS handler we will add a per-agent mpsc sender so
// we can forward the HUD command there. For now log and acknowledge.
log::info!(
"HUD command '{}' for session {} → agent {} (params: {})",
body.command,
session_id,
aid,
body.params
);
HttpResponse::Ok().json(ApiResponse::ok("command forwarded"))
// Build the forward message.
let msg = WsMessage::ForwardHudCommand {
command: body.command.clone(),
params: body.params.clone(),
};
let json = match serde_json::to_string(&msg) {
Ok(j) => j,
Err(e) => {
return HttpResponse::InternalServerError()
.json(ApiResponse::<()>::err(format!("serialization error: {}", e)));
}
None => HttpResponse::Conflict().json(ApiResponse::<()>::err("no agent connected for this session")),
};
// Send through the agent channel.
if state.send_to_agent(&session_id, &json).await {
HttpResponse::Ok().json(ApiResponse::ok("command forwarded"))
} else {
HttpResponse::Conflict()
.json(ApiResponse::<()>::err("no agent connected for this session"))
}
}

View File

@ -141,5 +141,6 @@ pub struct HealthInfo {
pub uptime_secs: u64,
pub active_sessions: usize,
pub connected_agents: usize,
pub connected_viewers: usize,
pub version: String,
}