server: api/sessions.rs — CRUD endpoints + HUD command forwarding

This commit is contained in:
Butterfly Dev 2026-04-07 03:09:32 +00:00
parent 40bf516264
commit 94a992d72a

View File

@ -0,0 +1,88 @@
use actix_web::{web, HttpResponse};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use crate::models::{ApiResponse, Session};
use crate::state::AppState;
/// `GET /api/sessions` — list every session.
pub async fn list_sessions(state: web::Data<Arc<AppState>>) -> HttpResponse {
let sessions: Vec<Session> = state.sessions.iter().map(|r| r.value().clone()).collect();
HttpResponse::Ok().json(ApiResponse::ok(sessions))
}
/// `POST /api/sessions` — create a new session.
pub async fn create_session(state: web::Data<Arc<AppState>>) -> HttpResponse {
match state.create_session() {
Ok(session) => HttpResponse::Created().json(ApiResponse::ok(session)),
Err(e) => HttpResponse::ServiceUnavailable().json(ApiResponse::<()>::err(e)),
}
}
/// `GET /api/sessions/{id}` — get a single session.
pub async fn get_session(
state: web::Data<Arc<AppState>>,
path: web::Path<String>,
) -> HttpResponse {
let id = path.into_inner();
match state.get_session(&id) {
Some(session) => HttpResponse::Ok().json(ApiResponse::ok(session)),
None => HttpResponse::NotFound().json(ApiResponse::<()>::err("session not found")),
}
}
/// `DELETE /api/sessions/{id}` — remove a session.
pub async fn delete_session(
state: web::Data<Arc<AppState>>,
path: web::Path<String>,
) -> HttpResponse {
let id = path.into_inner();
if state.remove_session(&id) {
HttpResponse::Ok().json(ApiResponse::ok("session deleted"))
} else {
HttpResponse::NotFound().json(ApiResponse::<()>::err("session not found"))
}
}
/// JSON body for HUD commands.
#[derive(Debug, Deserialize)]
pub struct HudCommandPayload {
pub command: String,
#[serde(default)]
pub params: serde_json::Value,
}
/// `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.
pub async fn send_hud_command(
state: web::Data<Arc<AppState>>,
path: web::Path<String>,
body: web::Json<HudCommandPayload>,
) -> 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"))
}
None => HttpResponse::Conflict().json(ApiResponse::<()>::err("no agent connected for this session")),
}
}