1use crate::error::LingerError;
2use crate::RequestId;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::BTreeMap;
6
7#[derive(Clone, Debug, Default, Serialize, PartialEq)]
10#[non_exhaustive]
11pub struct CreateConversationRequest {
12 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
15 pub metadata: BTreeMap<String, String>,
16 #[serde(flatten)]
19 pub extra: BTreeMap<String, Value>,
20}
21
22impl CreateConversationRequest {
23 pub fn builder() -> CreateConversationRequestBuilder {
26 CreateConversationRequestBuilder::default()
27 }
28}
29
30#[derive(Clone, Debug, Default)]
33#[non_exhaustive]
34pub struct CreateConversationRequestBuilder {
35 metadata: BTreeMap<String, String>,
36 extra: BTreeMap<String, Value>,
37}
38
39impl CreateConversationRequestBuilder {
40 pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
43 self.metadata.insert(key.into(), value.into());
44 self
45 }
46
47 pub fn extra(mut self, name: impl Into<String>, value: Value) -> Self {
50 self.extra.insert(name.into(), value);
51 self
52 }
53
54 pub fn build(self) -> Result<CreateConversationRequest, LingerError> {
57 validate_metadata(&self.metadata)?;
58 validate_extra_fields(&self.extra)?;
59 Ok(CreateConversationRequest {
60 metadata: self.metadata,
61 extra: self.extra,
62 })
63 }
64}
65
66#[derive(Clone, Debug, Default, Serialize, PartialEq)]
69#[non_exhaustive]
70pub struct ModifyConversationRequest {
71 #[serde(skip_serializing_if = "BTreeMap::is_empty")]
74 pub metadata: BTreeMap<String, String>,
75}
76
77impl ModifyConversationRequest {
78 pub fn builder() -> ModifyConversationRequestBuilder {
81 ModifyConversationRequestBuilder::default()
82 }
83}
84
85#[derive(Clone, Debug, Default)]
88#[non_exhaustive]
89pub struct ModifyConversationRequestBuilder {
90 metadata: BTreeMap<String, String>,
91}
92
93impl ModifyConversationRequestBuilder {
94 pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
97 self.metadata.insert(key.into(), value.into());
98 self
99 }
100
101 pub fn build(self) -> Result<ModifyConversationRequest, LingerError> {
104 validate_metadata(&self.metadata)?;
105 Ok(ModifyConversationRequest {
106 metadata: self.metadata,
107 })
108 }
109}
110
111#[derive(Clone, Debug, Serialize, PartialEq)]
114#[non_exhaustive]
115pub struct CreateConversationItemRequest {
116 pub item: Value,
119}
120
121impl CreateConversationItemRequest {
122 pub fn builder() -> CreateConversationItemRequestBuilder {
125 CreateConversationItemRequestBuilder::default()
126 }
127}
128
129#[derive(Clone, Debug, Default)]
132#[non_exhaustive]
133pub struct CreateConversationItemRequestBuilder {
134 item: Option<Value>,
135}
136
137impl CreateConversationItemRequestBuilder {
138 pub fn item(mut self, item: Value) -> Self {
141 self.item = Some(item);
142 self
143 }
144
145 pub fn build(self) -> Result<CreateConversationItemRequest, LingerError> {
148 let item = self
149 .item
150 .filter(|value| !value.is_null())
151 .ok_or_else(|| LingerError::invalid_config("item is required"))?;
152 Ok(CreateConversationItemRequest { item })
153 }
154}
155
156#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
159#[non_exhaustive]
160pub struct Conversation {
161 pub id: String,
164 pub object: String,
167 #[serde(default)]
170 pub created_at: Option<u64>,
171 #[serde(default)]
174 pub metadata: BTreeMap<String, String>,
175 #[serde(flatten)]
178 pub extra: BTreeMap<String, Value>,
179 #[serde(skip)]
182 request_id: Option<RequestId>,
183}
184
185impl Conversation {
186 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
187 self.request_id = request_id;
188 self
189 }
190
191 pub fn request_id(&self) -> Option<&RequestId> {
194 self.request_id.as_ref()
195 }
196}
197
198#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
201#[non_exhaustive]
202pub struct ConversationItem {
203 pub id: String,
206 pub object: String,
209 #[serde(default)]
212 pub created_at: Option<u64>,
213 #[serde(flatten)]
216 pub extra: BTreeMap<String, Value>,
217 #[serde(skip)]
220 request_id: Option<RequestId>,
221}
222
223impl ConversationItem {
224 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
225 self.request_id = request_id;
226 self
227 }
228
229 pub fn request_id(&self) -> Option<&RequestId> {
232 self.request_id.as_ref()
233 }
234}
235
236#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
239#[non_exhaustive]
240pub struct ConversationItemPage {
241 pub object: String,
244 #[serde(default)]
247 pub data: Vec<ConversationItem>,
248 #[serde(default)]
251 pub first_id: Option<String>,
252 #[serde(default)]
255 pub last_id: Option<String>,
256 pub has_more: bool,
259 #[serde(skip)]
262 request_id: Option<RequestId>,
263}
264
265impl ConversationItemPage {
266 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
267 self.request_id = request_id;
268 self
269 }
270
271 pub fn request_id(&self) -> Option<&RequestId> {
274 self.request_id.as_ref()
275 }
276}
277
278#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
281#[non_exhaustive]
282pub struct ConversationDeletion {
283 pub id: String,
286 pub object: String,
289 pub deleted: bool,
292 #[serde(skip)]
295 request_id: Option<RequestId>,
296}
297
298impl ConversationDeletion {
299 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
300 self.request_id = request_id;
301 self
302 }
303
304 pub fn request_id(&self) -> Option<&RequestId> {
307 self.request_id.as_ref()
308 }
309}
310
311#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
314#[non_exhaustive]
315pub struct ConversationItemDeletion {
316 pub id: String,
319 pub object: String,
322 pub deleted: bool,
325 #[serde(skip)]
328 request_id: Option<RequestId>,
329}
330
331impl ConversationItemDeletion {
332 pub(crate) fn with_request_id(mut self, request_id: Option<RequestId>) -> Self {
333 self.request_id = request_id;
334 self
335 }
336
337 pub fn request_id(&self) -> Option<&RequestId> {
340 self.request_id.as_ref()
341 }
342}
343
344fn validate_metadata(metadata: &BTreeMap<String, String>) -> Result<(), LingerError> {
345 for key in metadata.keys() {
346 if key.trim().is_empty() {
347 return Err(LingerError::invalid_config(
348 "metadata keys must not be empty",
349 ));
350 }
351 }
352 Ok(())
353}
354
355fn validate_extra_fields(extra: &BTreeMap<String, Value>) -> Result<(), LingerError> {
356 for (key, value) in extra {
357 if key.trim().is_empty() {
358 return Err(LingerError::invalid_config(
359 "extra field names must not be empty",
360 ));
361 }
362 if value.is_null() {
363 return Err(LingerError::invalid_config(format!(
364 "extra field {key} must not be null"
365 )));
366 }
367 }
368 Ok(())
369}