use rmcp::schemars;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ExtractionResult {
#[schemars(description = "Extraction results in discovery order")]
pub results: Vec<serde_json::Value>,
#[serde(default)]
#[schemars(description = "Non-fatal per-input errors")]
pub errors: Vec<serde_json::Value>,
#[schemars(description = "Aggregate extraction counts")]
pub summary: ExtractionSummaryOutput,
#[serde(default)]
#[schemars(description = "Final URLs reached after redirects during URL ingestion")]
pub crawl_final_urls: Vec<String>,
#[serde(default)]
#[schemars(description = "Total redirects followed while fetching or crawling URLs")]
pub crawl_redirect_count: usize,
#[serde(default)]
#[schemars(description = "Unique normalized URLs discovered by crawls")]
pub crawl_unique_normalized_urls: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ExtractionSummaryOutput {
pub inputs: usize,
pub results: usize,
pub errors: usize,
pub remote_urls: usize,
pub pages_crawled: usize,
pub documents_downloaded: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct DetectMimeTypeOutput {
#[schemars(description = "Detected MIME type string")]
pub mime_type: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct ListFormatsOutput {
#[schemars(description = "List of supported document formats")]
pub formats: Vec<serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct VersionOutput {
#[schemars(description = "Xberg library version string")]
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct CacheStatsOutput {
#[schemars(description = "Absolute path to the cache directory")]
pub directory: String,
#[schemars(description = "Total number of cached files")]
pub total_files: u64,
#[schemars(description = "Total cache size in megabytes")]
pub total_size_mb: f64,
#[schemars(description = "Available disk space in megabytes")]
pub available_space_mb: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct CacheClearOutput {
#[schemars(description = "Absolute path to the cache directory that was cleared")]
pub directory: String,
#[schemars(description = "Number of files removed")]
pub removed_files: u64,
#[schemars(description = "Disk space freed in megabytes")]
pub freed_mb: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct CacheWarmOutput {
#[schemars(description = "Absolute path to the Xberg-managed cache directory")]
pub cache_dir: String,
#[schemars(description = "Labels of models confirmed available after this call")]
pub available: Vec<String>,
#[schemars(description = "Labels of models confirmed newly downloaded during this call")]
pub downloaded: Vec<String>,
#[schemars(description = "Labels of models confirmed already present in the cache")]
pub already_cached: Vec<String>,
}
#[cfg(test)]
mod tests {
use std::collections::BTreeSet;
use super::ExtractionResult;
#[test]
fn should_not_require_optional_extraction_fields_in_output_schema() {
let schema = rmcp::handler::server::common::schema_for_output::<ExtractionResult>();
let required: BTreeSet<String> = schema
.get("required")
.and_then(|value| value.as_array())
.expect("schema must declare a top-level `required` array")
.iter()
.map(|entry| entry.as_str().expect("required entries must be strings").to_string())
.collect();
let expected: BTreeSet<String> = ["results", "summary"].into_iter().map(String::from).collect();
assert_eq!(required, expected);
}
}
#[derive(Debug, Clone, Serialize, Deserialize, schemars::JsonSchema)]
pub struct CacheManifestOutput {
#[schemars(description = "Xberg library version")]
pub xberg_version: String,
#[schemars(description = "Number of model files in the manifest")]
pub model_count: usize,
#[schemars(description = "Total size of all model files in bytes")]
pub total_size_bytes: u64,
#[schemars(description = "Model file entries")]
pub models: Vec<serde_json::Value>,
}