#![cfg(feature = "plugin")]
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum CompletionEvent {
Start,
Content { text: String },
Usage {
input_tokens: u32,
output_tokens: u32,
#[serde(skip_serializing_if = "Option::is_none")]
total_tokens: Option<u32>,
},
Done {
#[serde(skip_serializing_if = "Option::is_none")]
finish_reason: Option<String>,
},
Error {
message: String,
#[serde(skip_serializing_if = "Option::is_none")]
code: Option<String>,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ModelEvent {
Model(ModelInfo),
Done { count: usize },
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ModelInfo {
pub id: String,
pub name: String,
pub family: String,
pub service: String,
pub verified: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
pub capabilities: CapabilitySummary,
#[serde(skip_serializing_if = "Option::is_none")]
pub pricing: Option<PricingSummary>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct CapabilitySummary {
pub streaming: bool,
pub vision: bool,
pub functions: bool,
pub json_mode: bool,
pub multimodal: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct PricingSummary {
pub input_per_1m_tokens: f64,
pub output_per_1m_tokens: f64,
pub currency: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ServiceEvent {
Service(ServiceInfo),
Done { count: usize },
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct ServiceInfo {
pub name: String,
pub base_url: String,
pub model_count: usize,
pub message_format: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum VerifyEvent {
Starting { model_id: String },
Success { model_id: String, latency_ms: u64 },
Failed { model_id: String, error: String },
Skipped { model_id: String, reason: String },
Done {
total: usize,
passed: usize,
failed: usize,
skipped: usize,
},
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum QueryEvent {
Match(ModelInfo),
Done { count: usize },
}
impl From<&crate::config::ModelConfig> for ModelInfo {
fn from(config: &crate::config::ModelConfig) -> Self {
Self {
id: config.model.id.clone(),
name: config.model.name.clone(),
family: config.model.family.clone(),
service: config.model.service.clone(),
verified: config.model.status == crate::config::VerificationStatus::Verified,
version: config.model.version.clone(),
capabilities: CapabilitySummary {
streaming: config.capabilities.streaming,
vision: config.capabilities.vision,
functions: config.capabilities.functions,
json_mode: config.capabilities.json_mode,
multimodal: config.capabilities.multimodal,
},
pricing: Some(PricingSummary {
input_per_1m_tokens: config.pricing.input_per_1k_tokens * 1000.0,
output_per_1m_tokens: config.pricing.output_per_1k_tokens * 1000.0,
currency: format!("{:?}", config.pricing.currency),
}),
}
}
}
impl From<&crate::config::ServiceConfig> for ServiceInfo {
fn from(config: &crate::config::ServiceConfig) -> Self {
Self {
name: config.service.name.clone(),
base_url: config.service.base_url.clone(),
model_count: 0, message_format: format!("{:?}", config.message_builder.as_ref().unwrap_or(&Default::default())),
}
}
}