use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum MediaSource {
Artifact { uri: String },
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum MessagePart {
Text {
text: String,
},
Image {
source: MediaSource,
#[serde(default, skip_serializing_if = "Option::is_none")]
mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
alt_text: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
detail: Option<String>,
},
Audio {
source: MediaSource,
#[serde(default, skip_serializing_if = "Option::is_none")]
mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
transcript: Option<String>,
},
File {
source: MediaSource,
#[serde(default, skip_serializing_if = "Option::is_none")]
mime_type: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
name: Option<String>,
},
Json {
value: Value,
},
}
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct MessageContent {
#[serde(default)]
pub parts: Vec<MessagePart>,
}
impl MessageContent {
pub fn text(text: impl Into<String>) -> Self {
Self {
parts: vec![MessagePart::Text { text: text.into() }],
}
}
pub fn plain_text(&self) -> String {
self.parts
.iter()
.filter_map(|part| match part {
MessagePart::Text { text } => Some(text.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join("\n")
}
pub fn has_non_text_parts(&self) -> bool {
self.parts
.iter()
.any(|part| !matches!(part, MessagePart::Text { .. }))
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ConversationMessageRole {
User,
Assistant,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ConversationMessage {
pub message_id: String,
pub request_id: String,
pub role: ConversationMessageRole,
pub content: MessageContent,
pub created_at: String,
}