codex-helper-core 0.15.0

Core library for codex-helper.
Documentation
use axum::Json;
use axum::http::StatusCode;

use crate::logging::now_ms;
use crate::state::RuntimeConfigState;

use super::ProxyService;

#[derive(serde::Deserialize)]
pub(super) struct StationRuntimeMetaRequest {
    #[serde(default)]
    station_name: Option<String>,
    #[serde(default)]
    enabled: Option<bool>,
    #[serde(default)]
    level: Option<u8>,
    #[serde(default)]
    clear_enabled: bool,
    #[serde(default)]
    clear_level: bool,
    #[serde(default)]
    runtime_state: Option<RuntimeConfigState>,
    #[serde(default)]
    clear_runtime_state: bool,
}

impl StationRuntimeMetaRequest {
    fn target_name(&self) -> Result<&str, (StatusCode, String)> {
        self.station_name
            .as_deref()
            .map(str::trim)
            .filter(|name| !name.is_empty())
            .ok_or((
                StatusCode::BAD_REQUEST,
                "station_name is required".to_string(),
            ))
    }
}

pub(super) async fn apply_station_runtime_meta(
    proxy: ProxyService,
    Json(payload): Json<StationRuntimeMetaRequest>,
) -> Result<StatusCode, (StatusCode, String)> {
    let station_name = payload.target_name()?.to_string();

    if payload.enabled.is_none()
        && payload.level.is_none()
        && !payload.clear_enabled
        && !payload.clear_level
        && payload.runtime_state.is_none()
        && !payload.clear_runtime_state
    {
        return Err((
            StatusCode::BAD_REQUEST,
            "at least one runtime station action must be provided".to_string(),
        ));
    }

    let cfg = proxy.config.snapshot().await;
    let mgr = proxy.service_manager(cfg.as_ref());
    if !mgr.contains_station(station_name.as_str()) {
        return Err((
            StatusCode::NOT_FOUND,
            format!("station '{}' not found", station_name),
        ));
    }

    let now = now_ms();
    if payload.clear_enabled {
        proxy
            .state
            .clear_station_enabled_override(proxy.service_name, station_name.as_str())
            .await;
    } else if let Some(enabled) = payload.enabled {
        proxy
            .state
            .set_station_enabled_override(proxy.service_name, station_name.clone(), enabled, now)
            .await;
    }

    if payload.clear_level {
        proxy
            .state
            .clear_station_level_override(proxy.service_name, station_name.as_str())
            .await;
    } else if let Some(level) = payload.level {
        proxy
            .state
            .set_station_level_override(
                proxy.service_name,
                station_name.clone(),
                level.clamp(1, 10),
                now,
            )
            .await;
    }

    if payload.clear_runtime_state {
        proxy
            .state
            .clear_station_runtime_state_override(proxy.service_name, station_name.as_str())
            .await;
    } else if let Some(runtime_state) = payload.runtime_state {
        proxy
            .state
            .set_station_runtime_state_override(
                proxy.service_name,
                station_name.clone(),
                runtime_state,
                now,
            )
            .await;
    }

    Ok(StatusCode::NO_CONTENT)
}

pub(super) async fn list_stations(
    proxy: ProxyService,
) -> Result<Json<Vec<crate::dashboard_core::StationOption>>, (StatusCode, String)> {
    let cfg = proxy.config.snapshot().await;
    let mgr = proxy.service_manager(cfg.as_ref());
    let meta_overrides = proxy
        .state
        .get_station_meta_overrides(proxy.service_name)
        .await;
    let state_overrides = proxy
        .state
        .get_station_runtime_state_overrides(proxy.service_name)
        .await;
    Ok(Json(crate::dashboard_core::build_station_options_from_mgr(
        mgr,
        &meta_overrides,
        &state_overrides,
    )))
}