use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use super::Pagination;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct ToolCall {
pub id: Uuid,
pub function_name: String,
pub function_arguments: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub function_result: Option<serde_json::Value>,
pub created_at: DateTime<Utc>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum MessageType {
UserMessage,
AssistantMessage,
}
impl std::fmt::Display for MessageType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::UserMessage => write!(f, "user_message"),
Self::AssistantMessage => write!(f, "assistant_message"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseMessageTypeError(String);
impl std::fmt::Display for ParseMessageTypeError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Invalid message type: {}", self.0)
}
}
impl std::error::Error for ParseMessageTypeError {}
impl std::str::FromStr for MessageType {
type Err = ParseMessageTypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"user_message" => Ok(Self::UserMessage),
"assistant_message" => Ok(Self::AssistantMessage),
_ => Err(ParseMessageTypeError(s.to_string())),
}
}
}
impl TryFrom<&str> for MessageType {
type Error = ParseMessageTypeError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl TryFrom<String> for MessageType {
type Error = ParseMessageTypeError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum MessageRole {
User,
Assistant,
}
impl std::fmt::Display for MessageRole {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::User => write!(f, "user"),
Self::Assistant => write!(f, "assistant"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseMessageRoleError(String);
impl std::fmt::Display for ParseMessageRoleError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Invalid message role: {}", self.0)
}
}
impl std::error::Error for ParseMessageRoleError {}
impl std::str::FromStr for MessageRole {
type Err = ParseMessageRoleError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"user" => Ok(Self::User),
"assistant" => Ok(Self::Assistant),
_ => Err(ParseMessageRoleError(s.to_string())),
}
}
}
impl TryFrom<&str> for MessageRole {
type Error = ParseMessageRoleError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl TryFrom<String> for MessageRole {
type Error = ParseMessageRoleError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct Message {
pub id: Uuid,
#[serde(rename = "type")]
pub message_type: MessageType,
pub role: MessageRole,
pub content: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_calls: Option<Vec<ToolCall>>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AiResponseStatus {
Pending,
Complete,
Failed,
}
impl std::fmt::Display for AiResponseStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Pending => write!(f, "pending"),
Self::Complete => write!(f, "complete"),
Self::Failed => write!(f, "failed"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseAiResponseStatusError(String);
impl std::fmt::Display for ParseAiResponseStatusError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Invalid AI response status: {}", self.0)
}
}
impl std::error::Error for ParseAiResponseStatusError {}
impl std::str::FromStr for AiResponseStatus {
type Err = ParseAiResponseStatusError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"pending" => Ok(Self::Pending),
"complete" => Ok(Self::Complete),
"failed" => Ok(Self::Failed),
_ => Err(ParseAiResponseStatusError(s.to_string())),
}
}
}
impl TryFrom<&str> for AiResponseStatus {
type Error = ParseAiResponseStatusError;
fn try_from(value: &str) -> Result<Self, Self::Error> {
value.parse()
}
}
impl TryFrom<String> for AiResponseStatus {
type Error = ParseAiResponseStatusError;
fn try_from(value: String) -> Result<Self, Self::Error> {
value.parse()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct MessageResponse {
pub id: Uuid,
#[serde(rename = "type")]
pub message_type: MessageType,
pub role: MessageRole,
pub content: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_calls: Option<Vec<ToolCall>>,
pub chat_id: Uuid,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ai_response_status: Option<AiResponseStatus>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ai_response_message: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct ChatResource {
pub id: Uuid,
pub title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct ChatSummary {
pub id: Uuid,
pub title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub message_count: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub last_message_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct ChatDetail {
pub id: Uuid,
pub title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub messages: Vec<Message>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub pagination: Option<Pagination>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct ChatCollection {
pub chats: Vec<ChatSummary>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub struct RetryResponse {
pub message: String,
pub message_id: Uuid,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub(crate) struct CreateChatRequest {
pub title: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub(crate) struct UpdateChatRequest {
pub title: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
pub(crate) struct CreateMessageRequest {
pub content: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
}