gephyr 1.16.18

Gephyr is a headless local AI relay/proxy API handling OpenAI, Claude, and Gemini-compatible APIs
Documentation
use crate::proxy::state::{ModelCatalogState, RuntimeState};
use axum::{
    extract::State,
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};
use serde_json::{json, Value};
use tracing::trace;
pub async fn handle_detect_model(
    State(state): State<ModelCatalogState>,
    Json(body): Json<Value>,
) -> Response {
    let active_protocol = crate::proxy::handlers::traits::protocol_name(
        &crate::proxy::handlers::traits::HandlerProtocol::Claude,
    );
    let supported_protocols: Vec<&'static str> =
        crate::proxy::handlers::traits::all_handler_protocols()
            .iter()
            .map(crate::proxy::handlers::traits::protocol_name)
            .collect();
    trace!(
        protocol = active_protocol,
        supported = ?supported_protocols,
        "handle_detect_model invoked"
    );
    let model_name = body.get("model").and_then(|v| v.as_str()).unwrap_or("");

    if model_name.is_empty() {
        return (StatusCode::BAD_REQUEST, "Missing 'model' field").into_response();
    }
    let mapped_model = crate::proxy::common::model_mapping::resolve_model_route(
        model_name,
        &*state.custom_mapping.read().await,
    );
    let config = crate::proxy::mappers::common_utils::resolve_request_config(
        model_name,
        &mapped_model,
        &None,
        None,
        None,
        None,
    );
    let mut response = json!({
        "model": model_name,
        "mapped_model": mapped_model,
        "type": config.request_type,
        "features": {
            "has_web_search": config.inject_google_search,
            "is_image_gen": config.request_type == "image_gen"
        }
    });

    if let Some(img_conf) = config.image_config {
        if let Some(obj) = response.as_object_mut() {
            obj.insert("config".to_string(), img_conf);
        }
    }

    Json(response).into_response()
}

pub async fn handle_internal_status(State(state): State<RuntimeState>) -> Response {
    let running = *state.is_running.read().await;
    Json(json!({
        "status": "ok",
        "service_running": running,
        "port": state.port,
        "version": env!("CARGO_PKG_VERSION")
    }))
    .into_response()
}

pub async fn build_models_list_response(state: &ModelCatalogState) -> Json<Value> {
    use crate::proxy::common::model_mapping::get_all_dynamic_models;

    let model_ids = get_all_dynamic_models(&state.custom_mapping).await;

    let data: Vec<_> = model_ids
        .into_iter()
        .map(|id| {
            json!({
                "id": id,
                "object": "model",
                "created": 1706745600,
                "owned_by": "antigravity"
            })
        })
        .collect();

    Json(json!({
        "object": "list",
        "data": data
    }))
}