1use serde::{Deserialize, Serialize};
9
10use crate::{
11 ZaiResult,
12 client::error::{ZaiError, codes},
13};
14
15#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub struct ApplicationEnvelope<T> {
18 pub data: T,
20 pub code: i64,
22 pub message: String,
24 pub timestamp: i64,
26}
27
28#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
30pub struct ApplicationFileStatItem {
31 pub file_id: String,
33 pub code: i64,
35 pub msg: String,
37}
38
39pub type ApplicationFileStatsResponse = ApplicationEnvelope<Vec<ApplicationFileStatItem>>;
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
44pub struct ApplicationFileUploadSuccessInfo {
45 pub file_id: String,
47 pub file_name: String,
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
53pub struct ApplicationFileUploadFailInfo {
54 pub file_name: String,
56 pub fail_reason: String,
58}
59
60#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
62pub struct ApplicationFileUploadData {
63 pub success_info: Vec<ApplicationFileUploadSuccessInfo>,
65 pub fail_info: Vec<ApplicationFileUploadFailInfo>,
67}
68
69pub type ApplicationFileUploadResponse = ApplicationEnvelope<ApplicationFileUploadData>;
71
72#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
74pub struct ApplicationDocumentInfo {
75 pub id: String,
77 pub name: String,
79 pub url: String,
81 pub dtype: i64,
83}
84
85#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
87pub struct ApplicationSlicePosition {
88 pub x0: f32,
90 pub x1: f32,
92 pub top: f32,
94 pub bottom: f32,
96 pub page: i64,
98 pub height: f32,
100 pub width: f32,
102}
103
104#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
106pub struct ApplicationSliceInfo {
107 pub document_id: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
111 pub position: Option<ApplicationSlicePosition>,
112 #[serde(skip_serializing_if = "Option::is_none")]
114 pub line: Option<i64>,
115 #[serde(skip_serializing_if = "Option::is_none")]
117 pub sheet_name: Option<String>,
118 pub text: String,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
124pub struct ApplicationSliceImage {
125 pub text: String,
127 pub cos_url: String,
129}
130
131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
133pub struct ApplicationDocumentSlices {
134 pub document: ApplicationDocumentInfo,
136 pub slice_info: Vec<ApplicationSliceInfo>,
138 pub hide_positions: bool,
140 #[serde(skip_serializing_if = "Option::is_none")]
142 pub images: Option<Vec<ApplicationSliceImage>>,
143}
144
145#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
147pub struct ApplicationSliceInfoData {
148 pub document_slices: Vec<ApplicationDocumentSlices>,
150 pub has_old_document: bool,
152}
153
154pub type ApplicationSliceInfoResponse = ApplicationEnvelope<ApplicationSliceInfoData>;
156
157#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
159pub struct ApplicationConversationCreateData {
160 pub conversation_id: String,
162}
163
164pub type ApplicationConversationCreateResponse =
166 ApplicationEnvelope<ApplicationConversationCreateData>;
167
168#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
170pub struct ApplicationInputTemplate {
171 pub options: Vec<serde_json::Value>,
173}
174
175#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
177pub struct ApplicationVariable {
178 pub id: String,
180 pub name: String,
182 #[serde(rename = "type")]
184 pub type_: String,
185 pub tips: String,
187 pub allowed_values: Vec<String>,
189 pub input_template: ApplicationInputTemplate,
191}
192
193pub type ApplicationVariablesResponse = ApplicationEnvelope<Vec<ApplicationVariable>>;
195
196#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
198pub struct ApplicationHistoryData {
199 pub problems: Vec<String>,
201}
202
203pub type ApplicationHistoryResponse = ApplicationEnvelope<ApplicationHistoryData>;
205
206#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
208#[serde(rename_all = "camelCase")]
209pub struct ApplicationMessageData {
210 #[serde(skip_serializing_if = "Option::is_none")]
212 pub msg: Option<String>,
213 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
215 pub type_: Option<String>,
216 #[serde(skip_serializing_if = "Option::is_none")]
218 pub code: Option<String>,
219 #[serde(skip_serializing_if = "Option::is_none")]
221 pub file: Option<String>,
222 #[serde(skip_serializing_if = "Option::is_none")]
224 pub url: Option<String>,
225 #[serde(skip_serializing_if = "Option::is_none")]
227 pub cover_url: Option<String>,
228}
229
230#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
232pub struct ApplicationToolCallsData {
233 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
235 pub type_: Option<String>,
236 #[serde(skip_serializing_if = "Option::is_none")]
238 pub tool_calls_data: Option<serde_json::Map<String, serde_json::Value>>,
239}
240
241#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
243pub struct ApplicationInvokeEvent {
244 #[serde(skip_serializing_if = "Option::is_none")]
246 pub node_id: Option<String>,
247 #[serde(skip_serializing_if = "Option::is_none")]
249 pub node_name: Option<String>,
250 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
252 pub type_: Option<String>,
253 #[serde(skip_serializing_if = "Option::is_none")]
255 pub content: Option<String>,
256 #[serde(skip_serializing_if = "Option::is_none")]
258 pub time: Option<i64>,
259 #[serde(skip_serializing_if = "Option::is_none")]
261 pub tool_calls: Option<ApplicationToolCallsData>,
262}
263
264#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266pub struct ApplicationInvokeDelta {
267 #[serde(skip_serializing_if = "Option::is_none")]
269 pub content: Option<ApplicationMessageData>,
270 #[serde(skip_serializing_if = "Option::is_none")]
272 pub event: Option<ApplicationInvokeEvent>,
273 #[serde(skip_serializing_if = "Option::is_none")]
275 pub tool_calls: Option<ApplicationToolCallsData>,
276}
277
278#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
280pub struct ApplicationInvokeMessages {
281 #[serde(skip_serializing_if = "Option::is_none")]
283 pub content: Option<ApplicationMessageData>,
284 #[serde(skip_serializing_if = "Option::is_none")]
286 pub event: Option<Vec<ApplicationInvokeEvent>>,
287}
288
289#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
291pub struct ApplicationInvokeError {
292 #[serde(skip_serializing_if = "Option::is_none")]
294 pub code: Option<i64>,
295 #[serde(skip_serializing_if = "Option::is_none")]
297 pub msg: Option<String>,
298}
299
300#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
302pub struct ApplicationInvokeChoice {
303 #[serde(skip_serializing_if = "Option::is_none")]
305 pub index: Option<i64>,
306 #[serde(skip_serializing_if = "Option::is_none")]
308 pub finish_reason: Option<String>,
309 #[serde(skip_serializing_if = "Option::is_none")]
311 pub error_msg: Option<ApplicationInvokeError>,
312 #[serde(skip_serializing_if = "Option::is_none")]
314 pub delta: Option<ApplicationInvokeDelta>,
315 #[serde(skip_serializing_if = "Option::is_none")]
317 pub messages: Option<ApplicationInvokeMessages>,
318}
319
320#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
322#[serde(rename_all = "camelCase")]
323pub struct ApplicationInvokeUsage {
324 #[serde(skip_serializing_if = "Option::is_none")]
326 pub model: Option<String>,
327 #[serde(skip_serializing_if = "Option::is_none")]
329 pub node_name: Option<String>,
330 #[serde(skip_serializing_if = "Option::is_none")]
332 pub input_token_count: Option<i64>,
333 #[serde(skip_serializing_if = "Option::is_none")]
335 pub output_token_count: Option<i64>,
336 #[serde(skip_serializing_if = "Option::is_none")]
338 pub total_token_count: Option<i64>,
339}
340
341#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
347pub struct ApplicationInvokeResponse {
348 #[serde(skip_serializing_if = "Option::is_none")]
350 pub request_id: Option<String>,
351 #[serde(skip_serializing_if = "Option::is_none")]
353 pub conversation_id: Option<String>,
354 #[serde(skip_serializing_if = "Option::is_none")]
356 pub app_id: Option<String>,
357 #[serde(skip_serializing_if = "Option::is_none")]
359 pub choices: Option<Vec<ApplicationInvokeChoice>>,
360 #[serde(skip_serializing_if = "Option::is_none")]
362 pub usage: Option<Vec<ApplicationInvokeUsage>>,
363}
364
365impl ApplicationInvokeResponse {
366 pub fn validate(&self) -> ZaiResult<()> {
368 if self.request_id.is_some()
369 || self.conversation_id.is_some()
370 || self.app_id.is_some()
371 || self.choices.is_some()
372 || self.usage.is_some()
373 {
374 return Ok(());
375 }
376
377 Err(ZaiError::ApiError {
378 code: codes::SDK_VALIDATION,
379 message: "application invoke response contained no documented fields".to_owned(),
380 })
381 }
382}
383
384#[cfg(test)]
385mod tests {
386 use super::*;
387
388 #[test]
389 fn required_application_envelope_fields_do_not_default() {
390 let missing_code =
391 serde_json::from_value::<ApplicationHistoryResponse>(serde_json::json!({
392 "data": {"problems": []},
393 "message": "ok",
394 "timestamp": 1
395 }));
396 assert!(missing_code.is_err());
397 }
398
399 #[test]
400 fn invocation_uses_the_official_top_level_and_camel_case_fields() {
401 let response: ApplicationInvokeResponse = serde_json::from_value(serde_json::json!({
402 "request_id": "req-1",
403 "choices": [{
404 "index": 0,
405 "delta": {"content": {"type": "video", "coverUrl": "https://cover"}}
406 }],
407 "usage": [{"nodeName": "model", "totalTokenCount": 3}]
408 }))
409 .unwrap();
410
411 assert_eq!(response.request_id.as_deref(), Some("req-1"));
412 let choice = &response.choices.as_ref().unwrap()[0];
413 assert_eq!(
414 choice
415 .delta
416 .as_ref()
417 .unwrap()
418 .content
419 .as_ref()
420 .unwrap()
421 .cover_url
422 .as_deref(),
423 Some("https://cover")
424 );
425 assert_eq!(
426 response.usage.as_ref().unwrap()[0].total_token_count,
427 Some(3)
428 );
429 assert!(response.validate().is_ok());
430 assert!(
431 serde_json::from_value::<ApplicationInvokeResponse>(serde_json::json!({}))
432 .unwrap()
433 .validate()
434 .is_err()
435 );
436 }
437}