use std::sync::{Arc, Mutex};
use serde::{Deserialize, Serialize};
use tower::util::BoxCloneService;
use crate::{ExtractionConfig, XbergError, service::ExtractionRequest, types::ExtractedDocument};
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Copy)]
pub struct ApiSizeLimits {
pub max_request_body_bytes: usize,
pub max_multipart_field_bytes: usize,
}
impl Default for ApiSizeLimits {
fn default() -> Self {
Self {
max_request_body_bytes: 100 * 1024 * 1024,
max_multipart_field_bytes: 100 * 1024 * 1024,
}
}
}
impl ApiSizeLimits {
pub(crate) fn new(max_request_body_bytes: usize, max_multipart_field_bytes: usize) -> Self {
Self {
max_request_body_bytes,
max_multipart_field_bytes,
}
}
#[cfg(test)]
pub(crate) fn from_mb(max_request_body_mb: usize, max_multipart_field_mb: usize) -> Self {
Self {
max_request_body_bytes: max_request_body_mb * 1024 * 1024,
max_multipart_field_bytes: max_multipart_field_mb * 1024 * 1024,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct PluginStatus {
pub ocr_backends_count: usize,
pub ocr_backends: Vec<String>,
pub extractors_count: usize,
pub post_processors_count: usize,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct HealthResponse {
#[cfg_attr(feature = "api", schema(example = "healthy"))]
pub status: String,
#[cfg_attr(feature = "api", schema(example = "0.8.0"))]
pub version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub plugins: Option<PluginStatus>,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct InfoResponse {
#[cfg_attr(feature = "api", schema(example = "0.8.0"))]
pub version: String,
pub rust_backend: bool,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct ErrorResponse {
#[cfg_attr(feature = "api", schema(example = "ValidationError"))]
pub error_type: String,
#[cfg_attr(feature = "api", schema(example = "Invalid input provided"))]
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub traceback: Option<String>,
#[cfg_attr(feature = "api", schema(example = 400))]
pub status_code: u16,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Clone)]
pub struct ApiState {
pub default_config: Arc<ExtractionConfig>,
pub extraction_service: Arc<Mutex<BoxCloneService<ExtractionRequest, ExtractedDocument, XbergError>>>,
#[cfg(feature = "api")]
pub job_store: Arc<super::jobs::JobStore>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct AsyncJobResponse {
pub job_id: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
#[serde(rename_all = "snake_case")]
pub enum JobState {
Pending,
Running,
Completed,
Failed,
Cancelled,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct JobStatus {
pub job_id: String,
pub state: JobState,
pub created_at: String,
pub updated_at: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
pub type JobStatusResponse = JobStatus;
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct CacheStatsResponse {
#[cfg_attr(feature = "api", schema(example = "/tmp/xberg-cache"))]
pub directory: String,
pub total_files: usize,
pub total_size_mb: f64,
pub available_space_mb: f64,
pub oldest_file_age_days: f64,
pub newest_file_age_days: f64,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct CacheClearResponse {
#[cfg_attr(feature = "api", schema(example = "/tmp/xberg-cache"))]
pub directory: String,
pub removed_files: usize,
pub freed_mb: f64,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct VersionResponse {
#[cfg_attr(feature = "api", schema(example = "0.8.0"))]
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct DetectResponse {
#[cfg_attr(feature = "api", schema(example = "application/pdf"))]
pub mime_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct ManifestEntryResponse {
#[cfg_attr(feature = "api", schema(example = "paddle-ocr/det/model.onnx"))]
pub relative_path: String,
pub sha256: String,
pub size_bytes: u64,
pub source_url: String,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct ManifestResponse {
#[cfg_attr(feature = "api", schema(example = "0.8.0"))]
pub xberg_version: String,
pub total_size_bytes: u64,
pub model_count: usize,
pub models: Vec<ManifestEntryResponse>,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct WarmRequest {
#[serde(default)]
pub all_embeddings: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub embedding_model: Option<String>,
#[serde(default)]
pub ner: bool,
#[serde(default)]
pub all_ner_models: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub ner_model: Option<String>,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct WarmResponse {
pub cache_dir: String,
pub downloaded: Vec<String>,
pub already_cached: Vec<String>,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct OpenWebDocumentResponse {
pub page_content: String,
pub metadata: OpenWebDocumentMetadata,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct OpenWebDocumentMetadata {
#[cfg_attr(feature = "api", schema(example = "document.pdf"))]
pub source: String,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct DoclingCompatResponse {
pub document: DoclingCompatDocument,
#[cfg_attr(feature = "api", schema(example = "success"))]
pub status: String,
}
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "api", derive(utoipa::ToSchema))]
pub struct DoclingCompatDocument {
pub md_content: String,
}