use crate::mcp::{Annotations, Role};
use serde::{Deserialize, Serialize};
use serde_with::base64::Base64;
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ModelHint {
pub name: Option<String>,
}
impl ModelHint {
pub fn new() -> Self {
Self::default()
}
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct ModelPreferences {
pub hints: Option<Vec<ModelHint>>,
pub cost_priority: Option<f64>,
pub speed_priority: Option<f64>,
pub intelligence_priority: Option<f64>,
}
impl ModelPreferences {
pub fn new() -> Self {
Self::default()
}
pub fn with_hints(mut self, hints: Vec<ModelHint>) -> Self {
self.hints = Some(hints);
self
}
pub fn append_hint(mut self, hint: ModelHint) -> Self {
self.hints.get_or_insert_with(Vec::new).push(hint);
self
}
pub fn with_cost_priority(mut self, priority: f64) -> Self {
self.cost_priority = Some(priority);
self
}
pub fn with_speed_priority(mut self, priority: f64) -> Self {
self.speed_priority = Some(priority);
self
}
pub fn with_intelligence_priority(mut self, priority: f64) -> Self {
self.intelligence_priority = Some(priority);
self
}
}
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TextContent {
pub text: String,
pub annotations: Option<Annotations>,
}
impl TextContent {
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
annotations: None,
}
}
pub fn with_annotations(mut self, annotations: Annotations) -> Self {
self.annotations = Some(annotations);
self
}
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ImageContent {
#[serde_as(as = "Base64")]
pub data: Vec<u8>,
pub mime_type: String,
pub annotations: Option<Annotations>,
}
impl ImageContent {
pub fn new(data: Vec<u8>, mime_type: impl Into<String>) -> Self {
Self {
data,
mime_type: mime_type.into(),
annotations: None,
}
}
pub fn with_annotations(mut self, annotations: Annotations) -> Self {
self.annotations = Some(annotations);
self
}
}
#[serde_with::serde_as]
#[serde_with::skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AudioContent {
#[serde_as(as = "Base64")]
pub data: Vec<u8>,
pub mime_type: String,
pub annotations: Option<Annotations>,
}
impl AudioContent {
pub fn new(data: Vec<u8>, mime_type: impl Into<String>) -> Self {
Self {
data,
mime_type: mime_type.into(),
annotations: None,
}
}
pub fn with_annotations(mut self, annotations: Annotations) -> Self {
self.annotations = Some(annotations);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase", tag = "type")]
pub enum SamplingContent {
Text(TextContent),
Image(ImageContent),
Audio(AudioContent),
}
impl From<String> for SamplingContent {
fn from(text: String) -> Self {
Self::Text(TextContent::new(text))
}
}
impl From<&String> for SamplingContent {
fn from(text: &String) -> Self {
Self::Text(TextContent::new(text.to_string()))
}
}
impl From<&str> for SamplingContent {
fn from(text: &str) -> Self {
Self::Text(TextContent::new(text.to_string()))
}
}
impl SamplingContent {
pub fn new_text(text: impl Into<String>) -> Self {
Self::Text(TextContent::new(text))
}
pub fn new_image(data: Vec<u8>, mime_type: impl Into<String>) -> Self {
Self::Image(ImageContent::new(data, mime_type))
}
pub fn new_audio(data: Vec<u8>, mime_type: impl Into<String>) -> Self {
Self::Audio(AudioContent::new(data, mime_type))
}
pub fn with_annotations(mut self, annotations: Annotations) -> Self {
match &mut self {
Self::Text(c) => c.annotations = Some(annotations),
Self::Image(c) => c.annotations = Some(annotations),
Self::Audio(c) => c.annotations = Some(annotations),
}
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SamplingMessage {
pub role: Role,
pub content: SamplingContent,
}
impl SamplingMessage {
pub fn new(role: Role, content: SamplingContent) -> Self {
Self { role, content }
}
}