use super::router::MessageRouter;
use super::types::{ChannelType, HealthResponse, InboundMessage, OutboundMessage};
use crate::agent::AgentManager;
use axum::{
extract::State,
http::StatusCode,
response::IntoResponse,
routing::{get, post},
Json, Router,
};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::time::Instant;
use tokio::sync::RwLock;
#[derive(Debug, Deserialize)]
pub struct MessageRequest {
pub text: String,
pub session_id: Option<String>,
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, Serialize)]
pub struct MessageResponse {
pub text: String,
pub status: String,
pub error: Option<String>,
}
pub struct HttpChannel {
router: Arc<MessageRouter>,
start_time: Instant,
}
impl HttpChannel {
pub fn new(agent_manager: Arc<RwLock<AgentManager>>) -> Self {
Self {
router: Arc::new(MessageRouter::new(agent_manager)),
start_time: Instant::now(),
}
}
pub fn build_router(self: Arc<Self>) -> Router {
Router::new()
.route("/v1/health", get(Self::health_handler))
.route("/v1/message", post(Self::message_handler))
.with_state(self)
}
async fn health_handler(
State(channel): State<Arc<Self>>,
) -> impl IntoResponse {
let uptime = channel.start_time.elapsed().as_secs();
let response = HealthResponse {
status: Arc::from("ok"),
version: Arc::from(env!("CARGO_PKG_VERSION")),
uptime_secs: uptime,
};
Json(response)
}
async fn message_handler(
State(channel): State<Arc<Self>>,
Json(request): Json<MessageRequest>,
) -> impl IntoResponse {
let session_id = request.session_id
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string());
let inbound = InboundMessage {
text: Arc::from(request.text.as_str()),
session_id: Arc::from(session_id.as_str()),
channel: ChannelType::Http,
user_id: None,
metadata: request.metadata,
};
match channel.router.route(inbound).await {
Ok(response) => {
let json_response = MessageResponse {
text: response.text.to_string(),
status: "ok".to_string(),
error: response.error.map(|e| e.to_string()),
};
(StatusCode::OK, Json(json_response))
}
Err(e) => {
let json_response = MessageResponse {
text: String::new(),
status: "error".to_string(),
error: Some(e.to_string()),
};
(StatusCode::INTERNAL_SERVER_ERROR, Json(json_response))
}
}
}
}