#![allow(unused_imports)]
mod nonstreaming;
mod streaming;
use super::error::CompletionError;
use crate::persistence::{self, PersistentState};
use axum::{
Json, Router, extract,
response::{IntoResponse, Response},
routing::{delete, get, post},
};
use jiff::Timestamp;
use openai::schemas::{
ChatCompletionDeleted, ChatCompletionList, ChatCompletionMessageList, CompletionUsage,
CreateChatCompletionRequest_Variant2 as CreateChatCompletionRequest,
CreateChatCompletionResponse, Metadata,
};
use std::sync::{Arc, RwLock};
pub fn routes() -> Router {
Router::new()
.route("/", get(list))
.route("/{completion_id}", get(get_))
.route("/{completion_id}/messages", get(get_messages))
.route("/", post(create))
.route("/{completion_id}", post(update))
.route("/{completion_id}", delete(delete_))
.with_state(persistence::get_ref())
}
#[axum::debug_handler]
async fn list() -> Json<ChatCompletionList> {
Json(ChatCompletionList {
object: "list".into(),
data: vec![], first_id: "".into(),
last_id: "".into(),
has_more: false,
})
}
#[axum::debug_handler]
async fn get_(extract::Path(_): extract::Path<String>) -> Json<CreateChatCompletionResponse> {
Json(dummy_response()) }
#[axum::debug_handler]
async fn get_messages(extract::Path(_): extract::Path<String>) -> Json<ChatCompletionMessageList> {
Json(ChatCompletionMessageList {
object: "list".into(),
data: vec![], first_id: "".into(),
last_id: "".into(),
has_more: false,
})
}
#[axum::debug_handler]
async fn create(
extract::State(state): extract::State<Arc<RwLock<PersistentState>>>,
extract::Json(request): extract::Json<CreateChatCompletionRequest>,
) -> Response {
if request.model.is_empty() {
return CompletionError::EmptyModel.into_response();
}
if request.stream.unwrap_or_default() {
streaming::create(state, request).await.into_response()
} else {
nonstreaming::create(state, request).await.into_response()
}
}
#[axum::debug_handler]
async fn update(
extract::Path(_): extract::Path<String>,
extract::Json(_): extract::Json<Metadata>,
) -> Json<CreateChatCompletionResponse> {
Json(dummy_response()) }
#[axum::debug_handler]
async fn delete_(extract::Path(_): extract::Path<String>) -> Json<ChatCompletionDeleted> {
Json(ChatCompletionDeleted::default()) }
fn dummy_response() -> CreateChatCompletionResponse {
CreateChatCompletionResponse {
id: super::util::generate_openai_id("chatcmpl"),
object: "chat.completion".into(),
created: Timestamp::now().as_second(),
model: "gpt-4.1-2025-04-14".into(),
choices: vec![],
service_tier: None,
system_fingerprint: None,
usage: Some(CompletionUsage {
prompt_tokens: 0,
completion_tokens: 0,
total_tokens: 0,
prompt_tokens_details: Default::default(),
completion_tokens_details: Default::default(),
}),
}
}