use modkit_macros::domain_model;
use time::OffsetDateTime;
use uuid::Uuid;
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Chat {
pub id: Uuid,
pub tenant_id: Uuid,
pub user_id: Uuid,
pub model: String,
pub title: Option<String>,
pub is_temporary: bool,
pub created_at: OffsetDateTime,
pub updated_at: OffsetDateTime,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ChatDetail {
pub id: Uuid,
pub model: String,
pub title: Option<String>,
pub is_temporary: bool,
pub message_count: i64,
pub created_at: OffsetDateTime,
pub updated_at: OffsetDateTime,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct NewChat {
pub model: Option<String>,
pub title: Option<String>,
pub is_temporary: bool,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[allow(clippy::option_option)]
pub struct ChatPatch {
pub title: Option<Option<String>>,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Message {
pub id: Uuid,
pub request_id: Uuid,
pub role: String,
pub content: String,
pub attachments: Vec<AttachmentSummary>,
pub my_reaction: Option<ReactionKind>,
pub model: Option<String>,
pub input_tokens: Option<i64>,
pub output_tokens: Option<i64>,
pub created_at: OffsetDateTime,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AttachmentSummary {
pub attachment_id: Uuid,
pub kind: String,
pub filename: String,
pub status: String,
pub img_thumbnail: Option<ImgThumbnail>,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImgThumbnail {
pub content_type: String,
pub width: i32,
pub height: i32,
pub data_base64: String,
}
#[domain_model]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReactionKind {
Like,
Dislike,
}
impl ReactionKind {
#[must_use]
pub fn parse(s: &str) -> Option<Self> {
match s {
"like" => Some(Self::Like),
"dislike" => Some(Self::Dislike),
_ => None,
}
}
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Like => "like",
Self::Dislike => "dislike",
}
}
}
impl std::fmt::Display for ReactionKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Reaction {
pub message_id: Uuid,
pub kind: ReactionKind,
pub created_at: OffsetDateTime,
}
#[domain_model]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResolvedModel {
pub model_id: String,
pub provider_model_id: String,
pub provider_id: String,
pub display_name: String,
pub tier: String,
pub multiplier_display: String,
pub description: Option<String>,
pub multimodal_capabilities: Vec<String>,
pub context_window: u32,
pub max_file_size_mb: u32,
pub system_prompt: String,
pub tool_support: mini_chat_sdk::ModelToolSupport,
pub thread_summary_prompt: String,
pub max_output_tokens: u32,
}
impl From<&mini_chat_sdk::ModelCatalogEntry> for ResolvedModel {
fn from(e: &mini_chat_sdk::ModelCatalogEntry) -> Self {
Self {
model_id: e.id.clone(),
provider_model_id: e.provider_model_id.clone(),
provider_id: e.provider_id.clone(),
display_name: e.display_name.clone(),
tier: match e.tier {
mini_chat_sdk::ModelTier::Standard => "standard".to_owned(),
mini_chat_sdk::ModelTier::Premium => "premium".to_owned(),
},
multiplier_display: e.multiplier_display.clone(),
description: if e.description.is_empty() {
None
} else {
Some(e.description.clone())
},
multimodal_capabilities: e.multimodal_capabilities.clone(),
context_window: e.context_window,
max_file_size_mb: e.general_config.max_file_size_mb,
system_prompt: e.system_prompt.clone(),
tool_support: e.general_config.tool_support.clone(),
thread_summary_prompt: e.thread_summary_prompt.clone(),
max_output_tokens: e.max_output_tokens,
}
}
}