use std::sync::Arc;
use axum::Json;
use axum::extract::{Path, State};
use chrono::{DateTime, Utc};
use serde::Deserialize;
use crate::api::error::AppError;
use crate::api::server::AppState;
use oxios_kernel::{MaxingStart, MaxingWindow, TokenMaxingApi};
#[derive(Debug, Deserialize)]
pub struct StartRequest {
pub window: Option<WindowRequest>,
#[serde(default)]
pub manual: bool,
}
#[derive(Debug, Deserialize)]
pub struct WindowRequest {
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
}
fn tm(state: &State<Arc<AppState>>) -> Result<&TokenMaxingApi, AppError> {
state
.kernel
.token_maxing
.as_ref()
.ok_or_else(|| AppError::ServiceUnavailable("token-maxing subsystem unavailable".into()))
}
pub(crate) async fn handle_token_maxing_start(
state: State<Arc<AppState>>,
Json(req): Json<StartRequest>,
) -> Result<Json<serde_json::Value>, AppError> {
let api = tm(&state)?;
if !api.enabled() {
return Err(AppError::BadRequest(
"token-maxing is disabled or has no eligible subscription provider".into(),
));
}
let start = if req.manual {
MaxingStart::Manual
} else {
match req.window {
Some(w) => MaxingStart::Scheduled(MaxingWindow {
start: w.start,
end: w.end,
}),
None => MaxingStart::Manual,
}
};
let id = api
.launch(start)
.map_err(|e| AppError::BadRequest(e.to_string()))?;
Ok(Json(serde_json::json!({ "session_id": id })))
}
pub(crate) async fn handle_token_maxing_stop(
state: State<Arc<AppState>>,
) -> Result<Json<serde_json::Value>, AppError> {
let api = tm(&state)?;
api.stop();
Ok(Json(serde_json::json!({ "stopped": true })))
}
pub(crate) async fn handle_token_maxing_status(
state: State<Arc<AppState>>,
) -> Result<Json<oxios_kernel::MaxerStatus>, AppError> {
let api = tm(&state)?;
Ok(Json(api.status()))
}
pub(crate) async fn handle_token_maxing_sessions(
state: State<Arc<AppState>>,
) -> Result<Json<Vec<oxios_kernel::TokenMaxingSession>>, AppError> {
let api = tm(&state)?;
Ok(Json(api.sessions()))
}
pub(crate) async fn handle_token_maxing_session(
state: State<Arc<AppState>>,
Path(id): Path<String>,
) -> Result<Json<oxios_kernel::TokenMaxingSession>, AppError> {
let api = tm(&state)?;
api.session(&id)
.map(Json)
.ok_or_else(|| AppError::NotFound(format!("session {id} not found")))
}
pub(crate) async fn handle_token_maxing_providers(
state: State<Arc<AppState>>,
) -> Result<Json<serde_json::Value>, AppError> {
let api = tm(&state)?;
Ok(Json(serde_json::json!({
"enabled": api.enabled(),
"providers": api.snapshots(),
"recalibrations": api.recalibration_history(),
"cooldowns": api.cooldown_history(),
})))
}