1use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
2use validator::Validate;
3
4#[derive(Debug, Clone, Serialize, Validate)]
10pub struct KnowledgeResponse<T> {
11 #[serde(skip_serializing_if = "Option::is_none")]
13 pub data: Option<T>,
14 #[serde(skip_serializing_if = "Option::is_none")]
17 pub code: Option<i64>,
18 #[serde(skip_serializing_if = "Option::is_none")]
20 pub message: Option<String>,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub timestamp: Option<u64>,
24}
25
26#[derive(Deserialize)]
27struct KnowledgeResponseWire<T> {
28 data: Option<T>,
29 code: Option<i64>,
30 message: Option<String>,
31 timestamp: Option<u64>,
32}
33
34impl<'de, T> Deserialize<'de> for KnowledgeResponse<T>
35where
36 T: Deserialize<'de>,
37{
38 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39 where
40 D: Deserializer<'de>,
41 {
42 let wire = KnowledgeResponseWire::deserialize(deserializer)?;
43 if wire.data.is_none()
44 && wire.code.is_none()
45 && wire.message.is_none()
46 && wire.timestamp.is_none()
47 {
48 return Err(D::Error::custom(
49 "knowledge response contained no documented non-null fields",
50 ));
51 }
52 Ok(Self {
53 data: wire.data,
54 code: wire.code,
55 message: wire.message,
56 timestamp: wire.timestamp,
57 })
58 }
59}
60
61#[derive(Debug, Clone, Serialize, Validate)]
63pub struct KnowledgeOperationResponse {
64 #[serde(skip_serializing_if = "Option::is_none")]
68 pub code: Option<i64>,
69 #[serde(skip_serializing_if = "Option::is_none")]
71 pub message: Option<String>,
72 #[serde(skip_serializing_if = "Option::is_none")]
74 pub timestamp: Option<u64>,
75}
76
77#[derive(Deserialize)]
78struct KnowledgeOperationResponseWire {
79 code: Option<i64>,
80 message: Option<String>,
81 timestamp: Option<u64>,
82}
83
84impl<'de> Deserialize<'de> for KnowledgeOperationResponse {
85 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
86 where
87 D: Deserializer<'de>,
88 {
89 let wire = KnowledgeOperationResponseWire::deserialize(deserializer)?;
90 if wire.code.is_none() && wire.message.is_none() && wire.timestamp.is_none() {
91 return Err(D::Error::custom(
92 "knowledge operation response contained no documented non-null fields",
93 ));
94 }
95 Ok(Self {
96 code: wire.code,
97 message: wire.message,
98 timestamp: wire.timestamp,
99 })
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
105pub struct KnowledgeItem {
106 #[serde(skip_serializing_if = "Option::is_none")]
108 pub id: Option<String>,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub embedding_id: Option<u64>,
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub contextual: Option<u8>,
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub name: Option<String>,
118 #[serde(skip_serializing_if = "Option::is_none")]
120 pub description: Option<String>,
121 #[serde(skip_serializing_if = "Option::is_none")]
123 pub background: Option<String>,
124 #[serde(skip_serializing_if = "Option::is_none")]
126 pub icon: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
129 pub document_size: Option<u64>,
130 #[serde(skip_serializing_if = "Option::is_none")]
132 pub length: Option<u64>,
133 #[serde(skip_serializing_if = "Option::is_none")]
135 pub word_num: Option<u64>,
136}
137
138#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
140pub struct KnowledgeListData {
141 #[serde(skip_serializing_if = "Option::is_none")]
143 pub list: Option<Vec<KnowledgeItem>>,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub total: Option<u64>,
147}
148
149pub type KnowledgeListResponse = KnowledgeResponse<KnowledgeListData>;
151
152pub type KnowledgeGetResponse = KnowledgeResponse<KnowledgeItem>;
154
155#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
157pub struct KnowledgeUsageCounts {
158 #[serde(skip_serializing_if = "Option::is_none")]
160 pub word_num: Option<u64>,
161 #[serde(skip_serializing_if = "Option::is_none")]
163 pub length: Option<u64>,
164}
165
166#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
168pub struct KnowledgeCapacityData {
169 #[serde(skip_serializing_if = "Option::is_none")]
171 pub used: Option<KnowledgeUsageCounts>,
172 #[serde(skip_serializing_if = "Option::is_none")]
174 pub total: Option<KnowledgeUsageCounts>,
175}
176
177pub type KnowledgeCapacityResponse = KnowledgeResponse<KnowledgeCapacityData>;
179
180#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
182pub struct DocumentFailInfo {
183 #[serde(skip_serializing_if = "Option::is_none")]
185 pub embedding_code: Option<i64>,
186 #[serde(skip_serializing_if = "Option::is_none")]
188 pub embedding_msg: Option<String>,
189}
190
191#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
193pub struct DocumentItem {
194 #[serde(skip_serializing_if = "Option::is_none")]
196 pub id: Option<String>,
197 #[serde(skip_serializing_if = "Option::is_none")]
199 pub knowledge_type: Option<i64>,
200 #[serde(skip_serializing_if = "Option::is_none")]
202 pub custom_separator: Option<Vec<String>>,
203 #[serde(skip_serializing_if = "Option::is_none")]
205 pub sentence_size: Option<u64>,
206 #[serde(skip_serializing_if = "Option::is_none")]
208 pub length: Option<u64>,
209 #[serde(skip_serializing_if = "Option::is_none")]
211 pub word_num: Option<u64>,
212 #[serde(skip_serializing_if = "Option::is_none")]
214 pub name: Option<String>,
215 #[serde(skip_serializing_if = "Option::is_none")]
217 pub url: Option<String>,
218 #[serde(skip_serializing_if = "Option::is_none")]
220 pub embedding_stat: Option<i64>,
221 #[serde(rename = "failInfo", skip_serializing_if = "Option::is_none")]
223 pub fail_info: Option<DocumentFailInfo>,
224}
225
226pub type DocumentGetResponse = KnowledgeResponse<DocumentItem>;
228
229#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
231pub struct DocumentListData {
232 #[serde(skip_serializing_if = "Option::is_none")]
234 pub list: Option<Vec<DocumentItem>>,
235 #[serde(skip_serializing_if = "Option::is_none")]
237 pub total: Option<u64>,
238}
239
240pub type DocumentListResponse = KnowledgeResponse<DocumentListData>;
242
243#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
245pub struct DocumentUrlUploadSuccessInfo {
246 #[serde(rename = "documentId", skip_serializing_if = "Option::is_none")]
248 pub document_id: Option<String>,
249 #[serde(skip_serializing_if = "Option::is_none")]
251 pub url: Option<String>,
252}
253
254#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
256pub struct DocumentUrlUploadFailedInfo {
257 #[serde(skip_serializing_if = "Option::is_none")]
259 pub url: Option<String>,
260 #[serde(rename = "failReason", skip_serializing_if = "Option::is_none")]
262 pub fail_reason: Option<String>,
263}
264
265#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
267pub struct DocumentUrlUploadData {
268 #[serde(rename = "successInfos", skip_serializing_if = "Option::is_none")]
270 pub success_infos: Option<Vec<DocumentUrlUploadSuccessInfo>>,
271 #[serde(rename = "failedInfos", skip_serializing_if = "Option::is_none")]
273 pub failed_infos: Option<Vec<DocumentUrlUploadFailedInfo>>,
274}
275
276pub type DocumentUrlUploadResponse = KnowledgeResponse<DocumentUrlUploadData>;
278
279#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
281pub struct DocumentUploadSuccessInfo {
282 #[serde(rename = "documentId", skip_serializing_if = "Option::is_none")]
284 pub document_id: Option<String>,
285 #[serde(rename = "fileName", skip_serializing_if = "Option::is_none")]
287 pub file_name: Option<String>,
288}
289
290#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
292pub struct DocumentUploadFailedInfo {
293 #[serde(rename = "fileName", skip_serializing_if = "Option::is_none")]
295 pub file_name: Option<String>,
296 #[serde(rename = "failReason", skip_serializing_if = "Option::is_none")]
298 pub fail_reason: Option<String>,
299}
300
301#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
303pub struct DocumentUploadData {
304 #[serde(rename = "successInfos", skip_serializing_if = "Option::is_none")]
306 pub success_infos: Option<Vec<DocumentUploadSuccessInfo>>,
307 #[serde(rename = "failedInfos", skip_serializing_if = "Option::is_none")]
309 pub failed_infos: Option<Vec<DocumentUploadFailedInfo>>,
310}
311
312#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
314pub struct DocumentImageItem {
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub text: Option<String>,
318 #[serde(skip_serializing_if = "Option::is_none")]
320 pub cos_url: Option<String>,
321}
322
323#[derive(Debug, Clone, Serialize, Deserialize, Validate)]
325pub struct DocumentImageListData {
326 #[serde(skip_serializing_if = "Option::is_none")]
328 pub images: Option<Vec<DocumentImageItem>>,
329}
330
331pub type DocumentImageListResponse = KnowledgeResponse<DocumentImageListData>;
333
334pub type DocumentUploadResponse = KnowledgeResponse<DocumentUploadData>;
336
337#[cfg(test)]
338mod tests {
339 use super::*;
340
341 #[test]
342 fn success_envelopes_follow_optional_schema_and_reject_empty_success() {
343 assert!(
344 serde_json::from_value::<KnowledgeResponse<serde_json::Value>>(
345 serde_json::json!({"code": 200})
346 )
347 .is_ok()
348 );
349 assert!(
350 serde_json::from_value::<KnowledgeResponse<serde_json::Value>>(
351 serde_json::json!({"data": {}})
352 )
353 .is_ok()
354 );
355 assert!(
356 serde_json::from_value::<KnowledgeResponse<serde_json::Value>>(serde_json::json!({}))
357 .is_err()
358 );
359 assert!(
360 serde_json::from_value::<KnowledgeResponse<serde_json::Value>>(
361 serde_json::json!({"data": null, "code": null})
362 )
363 .is_err()
364 );
365 assert!(
366 serde_json::from_value::<KnowledgeOperationResponse>(serde_json::json!({
367 "unknown": "value"
368 }))
369 .is_err()
370 );
371 assert!(
372 serde_json::from_value::<KnowledgeOperationResponse>(serde_json::json!({
373 "message": "ok"
374 }))
375 .is_ok()
376 );
377 }
378}