use axum::http::Method;
use axum::response::Response;
use crate::event::{ProxyEvent, SessionEndEvent, SessionStartEvent};
use crate::protocol::McpMethod;
use crate::protocol::session::{SessionState, SessionStore};
use crate::proxy::ProxyState;
use crate::proxy::pipeline::context::RequestContext;
use crate::proxy::pipeline::emit::normalize_platform;
pub async fn touch(state: &ProxyState, ctx: &RequestContext) {
let Some(sid) = ctx.session_id.as_deref() else {
return;
};
state.sessions.touch(sid).await;
if ctx.mcp_method == Some(McpMethod::Initialized) {
state.sessions.update_state(sid, SessionState::Active).await;
}
}
pub async fn maybe_handle_delete(state: &ProxyState, ctx: &RequestContext) -> Option<Response> {
if ctx.http_method != Method::DELETE {
return None;
}
let sid = ctx.session_id.as_deref()?;
state
.event_bus
.emit(ProxyEvent::SessionEnd(SessionEndEvent {
session_id: sid.to_string(),
ts: chrono::Utc::now().timestamp_millis(),
}));
state.sessions.remove(sid).await;
None
}
pub async fn maybe_record_start(
state: &ProxyState,
ctx: &RequestContext,
method: &McpMethod,
status: u16,
) {
if *method != McpMethod::Initialize || status >= 400 {
return;
}
let Some(sid) = ctx.session_id.as_deref() else {
return;
};
state.sessions.create(sid).await;
state
.sessions
.update_state(sid, SessionState::Initialized)
.await;
let (client_name, client_version, client_platform) =
if let Some(info) = ctx.client_info_from_init.clone() {
let platform = normalize_platform(&info.name).to_string();
let name = info.name.clone();
let version = info.version.clone();
state.sessions.set_client_info(sid, info).await;
(Some(name), version, Some(platform))
} else {
(None, None, None)
};
state
.event_bus
.emit(ProxyEvent::SessionStart(SessionStartEvent {
session_id: sid.to_string(),
proxy: state.name.clone(),
ts: chrono::Utc::now().timestamp_millis(),
client_name,
client_version,
client_platform,
}));
}