sure_client_rs/models/
chat.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use super::Pagination;
6
7/// Tool call information
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
9#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
10pub struct ToolCall {
11    /// Tool call ID
12    pub id: Uuid,
13    /// Function name
14    pub function_name: String,
15    /// Function arguments
16    pub function_arguments: serde_json::Value,
17    /// Function result
18    #[serde(default, skip_serializing_if = "Option::is_none")]
19    pub function_result: Option<serde_json::Value>,
20    /// Creation timestamp
21    pub created_at: DateTime<Utc>,
22}
23
24/// Message type
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
26#[serde(rename_all = "snake_case")]
27pub enum MessageType {
28    /// User message
29    UserMessage,
30    /// Assistant message
31    AssistantMessage,
32}
33
34impl std::fmt::Display for MessageType {
35    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36        match self {
37            Self::UserMessage => write!(f, "user_message"),
38            Self::AssistantMessage => write!(f, "assistant_message"),
39        }
40    }
41}
42
43/// Error returned when parsing a `MessageType` from a string fails.
44#[derive(Debug, Clone, PartialEq, Eq)]
45pub struct ParseMessageTypeError(String);
46
47impl std::fmt::Display for ParseMessageTypeError {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        write!(f, "Invalid message type: {}", self.0)
50    }
51}
52
53impl std::error::Error for ParseMessageTypeError {}
54
55impl std::str::FromStr for MessageType {
56    type Err = ParseMessageTypeError;
57
58    fn from_str(s: &str) -> Result<Self, Self::Err> {
59        match s {
60            "user_message" => Ok(Self::UserMessage),
61            "assistant_message" => Ok(Self::AssistantMessage),
62            _ => Err(ParseMessageTypeError(s.to_string())),
63        }
64    }
65}
66
67impl TryFrom<&str> for MessageType {
68    type Error = ParseMessageTypeError;
69
70    fn try_from(value: &str) -> Result<Self, Self::Error> {
71        value.parse()
72    }
73}
74
75impl TryFrom<String> for MessageType {
76    type Error = ParseMessageTypeError;
77
78    fn try_from(value: String) -> Result<Self, Self::Error> {
79        value.parse()
80    }
81}
82
83/// Message role
84#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
85#[serde(rename_all = "lowercase")]
86pub enum MessageRole {
87    /// User role
88    User,
89    /// Assistant role
90    Assistant,
91}
92
93impl std::fmt::Display for MessageRole {
94    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95        match self {
96            Self::User => write!(f, "user"),
97            Self::Assistant => write!(f, "assistant"),
98        }
99    }
100}
101
102/// Error returned when parsing a `MessageRole` from a string fails.
103#[derive(Debug, Clone, PartialEq, Eq)]
104pub struct ParseMessageRoleError(String);
105
106impl std::fmt::Display for ParseMessageRoleError {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        write!(f, "Invalid message role: {}", self.0)
109    }
110}
111
112impl std::error::Error for ParseMessageRoleError {}
113
114impl std::str::FromStr for MessageRole {
115    type Err = ParseMessageRoleError;
116
117    fn from_str(s: &str) -> Result<Self, Self::Err> {
118        match s {
119            "user" => Ok(Self::User),
120            "assistant" => Ok(Self::Assistant),
121            _ => Err(ParseMessageRoleError(s.to_string())),
122        }
123    }
124}
125
126impl TryFrom<&str> for MessageRole {
127    type Error = ParseMessageRoleError;
128
129    fn try_from(value: &str) -> Result<Self, Self::Error> {
130        value.parse()
131    }
132}
133
134impl TryFrom<String> for MessageRole {
135    type Error = ParseMessageRoleError;
136
137    fn try_from(value: String) -> Result<Self, Self::Error> {
138        value.parse()
139    }
140}
141
142/// Message in a chat
143#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
144#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
145pub struct Message {
146    /// Message ID
147    pub id: Uuid,
148    /// Message type
149    #[serde(rename = "type")]
150    pub message_type: MessageType,
151    /// Message role
152    pub role: MessageRole,
153    /// Message content
154    pub content: String,
155    /// Model identifier
156    #[serde(default, skip_serializing_if = "Option::is_none")]
157    pub model: Option<String>,
158    /// Creation timestamp
159    pub created_at: DateTime<Utc>,
160    /// Last update timestamp
161    pub updated_at: DateTime<Utc>,
162    /// Tool calls associated with this message
163    #[serde(default, skip_serializing_if = "Option::is_none")]
164    pub tool_calls: Option<Vec<ToolCall>>,
165}
166
167/// AI response status
168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
169#[serde(rename_all = "lowercase")]
170pub enum AiResponseStatus {
171    /// Pending
172    Pending,
173    /// Complete
174    Complete,
175    /// Failed
176    Failed,
177}
178
179impl std::fmt::Display for AiResponseStatus {
180    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181        match self {
182            Self::Pending => write!(f, "pending"),
183            Self::Complete => write!(f, "complete"),
184            Self::Failed => write!(f, "failed"),
185        }
186    }
187}
188
189/// Error returned when parsing an `AiResponseStatus` from a string fails.
190#[derive(Debug, Clone, PartialEq, Eq)]
191pub struct ParseAiResponseStatusError(String);
192
193impl std::fmt::Display for ParseAiResponseStatusError {
194    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195        write!(f, "Invalid AI response status: {}", self.0)
196    }
197}
198
199impl std::error::Error for ParseAiResponseStatusError {}
200
201impl std::str::FromStr for AiResponseStatus {
202    type Err = ParseAiResponseStatusError;
203
204    fn from_str(s: &str) -> Result<Self, Self::Err> {
205        match s {
206            "pending" => Ok(Self::Pending),
207            "complete" => Ok(Self::Complete),
208            "failed" => Ok(Self::Failed),
209            _ => Err(ParseAiResponseStatusError(s.to_string())),
210        }
211    }
212}
213
214impl TryFrom<&str> for AiResponseStatus {
215    type Error = ParseAiResponseStatusError;
216
217    fn try_from(value: &str) -> Result<Self, Self::Error> {
218        value.parse()
219    }
220}
221
222impl TryFrom<String> for AiResponseStatus {
223    type Error = ParseAiResponseStatusError;
224
225    fn try_from(value: String) -> Result<Self, Self::Error> {
226        value.parse()
227    }
228}
229
230/// Message response with additional fields
231#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
232#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
233pub struct MessageResponse {
234    /// Message ID
235    pub id: Uuid,
236    /// Message type
237    #[serde(rename = "type")]
238    pub message_type: MessageType,
239    /// Message role
240    pub role: MessageRole,
241    /// Message content
242    pub content: String,
243    /// Model identifier
244    #[serde(default, skip_serializing_if = "Option::is_none")]
245    pub model: Option<String>,
246    /// Creation timestamp
247    pub created_at: DateTime<Utc>,
248    /// Last update timestamp
249    pub updated_at: DateTime<Utc>,
250    /// Tool calls associated with this message
251    #[serde(default, skip_serializing_if = "Option::is_none")]
252    pub tool_calls: Option<Vec<ToolCall>>,
253    /// Chat ID
254    pub chat_id: Uuid,
255    /// AI response status
256    #[serde(default, skip_serializing_if = "Option::is_none")]
257    pub ai_response_status: Option<AiResponseStatus>,
258    /// AI response message
259    #[serde(default, skip_serializing_if = "Option::is_none")]
260    pub ai_response_message: Option<String>,
261}
262
263/// Chat resource base information
264#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
265#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
266pub struct ChatResource {
267    /// Chat ID
268    pub id: Uuid,
269    /// Chat title
270    pub title: String,
271    /// Error message (if any)
272    #[serde(default, skip_serializing_if = "Option::is_none")]
273    pub error: Option<String>,
274    /// Creation timestamp
275    pub created_at: DateTime<Utc>,
276    /// Last update timestamp
277    pub updated_at: DateTime<Utc>,
278}
279
280/// Chat summary with message count
281#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
282#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
283pub struct ChatSummary {
284    /// Chat ID
285    pub id: Uuid,
286    /// Chat title
287    pub title: String,
288    /// Error message (if any)
289    #[serde(default, skip_serializing_if = "Option::is_none")]
290    pub error: Option<String>,
291    /// Creation timestamp
292    pub created_at: DateTime<Utc>,
293    /// Last update timestamp
294    pub updated_at: DateTime<Utc>,
295    /// Number of messages in the chat
296    pub message_count: u32,
297    /// Timestamp of last message
298    #[serde(default, skip_serializing_if = "Option::is_none")]
299    pub last_message_at: Option<DateTime<Utc>>,
300}
301
302/// Detailed chat information with messages
303#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
304#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
305pub struct ChatDetail {
306    /// Chat ID
307    pub id: Uuid,
308    /// Chat title
309    pub title: String,
310    /// Error message (if any)
311    #[serde(default, skip_serializing_if = "Option::is_none")]
312    pub error: Option<String>,
313    /// Creation timestamp
314    pub created_at: DateTime<Utc>,
315    /// Last update timestamp
316    pub updated_at: DateTime<Utc>,
317    /// Messages in the chat
318    pub messages: Vec<Message>,
319    /// Pagination information (if paginated)
320    #[serde(default, skip_serializing_if = "Option::is_none")]
321    pub pagination: Option<Pagination>,
322}
323
324/// Collection of chat summaries
325#[derive(Debug, Clone, Serialize, Deserialize)]
326#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
327pub struct ChatCollection {
328    /// List of chats
329    pub chats: Vec<ChatSummary>,
330}
331
332/// Retry response
333#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
334#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
335pub struct RetryResponse {
336    /// Response message
337    pub message: String,
338    /// Message ID
339    pub message_id: Uuid,
340}
341
342/// Create chat request
343#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
344#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
345pub(crate) struct CreateChatRequest {
346    /// Chat title
347    pub title: String,
348    /// Optional initial message
349    #[serde(default, skip_serializing_if = "Option::is_none")]
350    pub message: Option<String>,
351    /// Optional OpenAI model identifier
352    #[serde(default, skip_serializing_if = "Option::is_none")]
353    pub model: Option<String>,
354}
355
356/// Update chat request
357#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
358#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
359pub(crate) struct UpdateChatRequest {
360    /// Updated chat title
361    pub title: String,
362}
363
364/// Create message request
365#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
366#[cfg_attr(feature = "strict", serde(deny_unknown_fields))]
367pub(crate) struct CreateMessageRequest {
368    /// Message content
369    pub content: String,
370    /// Optional model identifier
371    #[serde(default, skip_serializing_if = "Option::is_none")]
372    pub model: Option<String>,
373}