nylas_types/
smart_compose.rs1use serde::{Deserialize, Serialize};
6
7use crate::MessageId;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
27pub struct SmartComposeRequest {
28 pub prompt: String,
30
31 #[serde(skip_serializing_if = "Option::is_none")]
33 pub message_id: Option<MessageId>,
34
35 #[serde(skip_serializing_if = "Option::is_none")]
38 pub temperature: Option<f32>,
39}
40
41impl SmartComposeRequest {
42 pub fn new(prompt: impl Into<String>) -> Self {
44 Self {
45 prompt: prompt.into(),
46 message_id: None,
47 temperature: None,
48 }
49 }
50
51 pub fn reply_to(prompt: impl Into<String>, message_id: MessageId) -> Self {
53 Self {
54 prompt: prompt.into(),
55 message_id: Some(message_id),
56 temperature: None,
57 }
58 }
59
60 pub fn with_temperature(mut self, temperature: f32) -> Self {
62 self.temperature = Some(temperature);
63 self
64 }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
82pub struct SmartComposeResponse {
83 pub suggestion: String,
85}
86
87#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
109pub struct SmartComposeStreamEvent {
110 #[serde(rename = "type")]
112 pub event_type: String,
113
114 #[serde(skip_serializing_if = "Option::is_none")]
116 pub content: Option<String>,
117
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub error: Option<String>,
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn test_smart_compose_request_new() {
129 let request = SmartComposeRequest::new("Write a professional email");
130
131 assert_eq!(request.prompt, "Write a professional email");
132 assert_eq!(request.message_id, None);
133 assert_eq!(request.temperature, None);
134 }
135
136 #[test]
137 fn test_smart_compose_request_reply_to() {
138 let message_id = MessageId::new("msg_123");
139 let request = SmartComposeRequest::reply_to("Write a polite decline", message_id.clone());
140
141 assert_eq!(request.prompt, "Write a polite decline");
142 assert_eq!(request.message_id, Some(message_id));
143 assert_eq!(request.temperature, None);
144 }
145
146 #[test]
147 fn test_smart_compose_request_with_temperature() {
148 let request = SmartComposeRequest::new("Generate email").with_temperature(0.7);
149
150 assert_eq!(request.temperature, Some(0.7));
151 }
152
153 #[test]
154 fn test_smart_compose_request_serialization() {
155 let request = SmartComposeRequest::new("Test prompt").with_temperature(0.5);
156
157 let json = serde_json::to_string(&request).unwrap();
158 assert!(json.contains("Test prompt"));
159 assert!(json.contains("0.5"));
160
161 let deserialized: SmartComposeRequest = serde_json::from_str(&json).unwrap();
162 assert_eq!(deserialized.prompt, "Test prompt");
163 assert_eq!(deserialized.temperature, Some(0.5));
164 }
165
166 #[test]
167 fn test_smart_compose_response_deserialization() {
168 let json = r#"{"suggestion":"Dear John,\n\nI hope this finds you well."}"#;
169 let response: SmartComposeResponse = serde_json::from_str(json).unwrap();
170
171 assert!(response.suggestion.contains("Dear John"));
172 }
173
174 #[test]
175 fn test_smart_compose_stream_event_content() {
176 let json = r#"{"type":"content","content":"Hello "}"#;
177 let event: SmartComposeStreamEvent = serde_json::from_str(json).unwrap();
178
179 assert_eq!(event.event_type, "content");
180 assert_eq!(event.content, Some("Hello ".to_string()));
181 assert_eq!(event.error, None);
182 }
183
184 #[test]
185 fn test_smart_compose_stream_event_done() {
186 let json = r#"{"type":"done"}"#;
187 let event: SmartComposeStreamEvent = serde_json::from_str(json).unwrap();
188
189 assert_eq!(event.event_type, "done");
190 assert_eq!(event.content, None);
191 assert_eq!(event.error, None);
192 }
193
194 #[test]
195 fn test_smart_compose_stream_event_error() {
196 let json = r#"{"type":"error","error":"Rate limit exceeded"}"#;
197 let event: SmartComposeStreamEvent = serde_json::from_str(json).unwrap();
198
199 assert_eq!(event.event_type, "error");
200 assert_eq!(event.error, Some("Rate limit exceeded".to_string()));
201 assert_eq!(event.content, None);
202 }
203}