zai_rs/tool/file_parser_create/
data.rs1use std::{path::Path, sync::Arc};
7
8use tracing::{debug, trace, warn};
9
10use super::{request::*, response::*};
11use crate::{
12 ZaiResult,
13 client::{
14 endpoints::{ApiBase, EndpointConfig, paths},
15 error::codes,
16 http::{HttpClientConfig, parse_typed_response, send_multipart_request},
17 },
18};
19
20pub struct FileParserCreateRequest {
42 pub key: String,
44 url: String,
45 endpoint_config: EndpointConfig,
46 api_base: ApiBase,
47 http_config: Arc<HttpClientConfig>,
48 pub file_path: std::path::PathBuf,
50 pub tool_type: ToolType,
52 pub file_type: FileType,
54}
55
56impl FileParserCreateRequest {
57 pub fn new(
71 key: String,
72 file_path: &Path,
73 tool_type: ToolType,
74 file_type: FileType,
75 ) -> crate::ZaiResult<Self> {
76 if !file_path.exists() {
78 return Err(crate::client::error::ZaiError::FileError {
79 code: codes::SDK_FILE_NOT_FOUND,
80 message: format!("File does not exist: {}", file_path.display()),
81 });
82 }
83
84 if !file_type.is_supported_by(&tool_type) {
86 return Err(crate::client::error::ZaiError::ApiError {
87 code: 1200,
88 message: format!(
89 "File type {:?} is not supported by tool type {:?}",
90 file_type, tool_type
91 ),
92 });
93 }
94
95 let endpoint_config = EndpointConfig::default();
96 let api_base = ApiBase::PaasV4;
97 let url = endpoint_config.url(&api_base, paths::FILE_PARSER_CREATE);
98
99 Ok(Self {
100 key,
101 url,
102 endpoint_config,
103 api_base,
104 http_config: Arc::new(HttpClientConfig::default()),
105 file_path: file_path.to_path_buf(),
106 tool_type,
107 file_type,
108 })
109 }
110
111 pub fn new_with_auto_type(
125 key: String,
126 file_path: &Path,
127 tool_type: ToolType,
128 ) -> crate::ZaiResult<Self> {
129 let file_type = FileType::from_path(file_path).ok_or_else(|| {
130 crate::client::error::ZaiError::FileError {
131 code: codes::SDK_FILE_TYPE_UNSUPPORTED,
132 message: format!(
133 "Could not determine file type from path: {}",
134 file_path.display()
135 ),
136 }
137 })?;
138
139 Self::new(key, file_path, tool_type, file_type)
140 }
141
142 pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
143 self.api_base = ApiBase::Custom(base_url.into());
144 self.url = self
145 .endpoint_config
146 .url(&self.api_base, paths::FILE_PARSER_CREATE);
147 self
148 }
149
150 pub fn with_endpoint_config(mut self, endpoint_config: EndpointConfig) -> Self {
151 self.endpoint_config = endpoint_config;
152 self.url = self
153 .endpoint_config
154 .url(&self.api_base, paths::FILE_PARSER_CREATE);
155 self
156 }
157
158 pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
159 self.http_config = Arc::new(config);
160 self
161 }
162
163 pub async fn send(&self) -> ZaiResult<FileParserCreateResponse> {
169 debug!(file = %self.file_path.display(), "Creating file parser task");
170
171 let file_bytes = tokio::fs::read(&self.file_path).await?;
172 let file_name = self
173 .file_path
174 .file_name()
175 .unwrap_or_default()
176 .to_string_lossy()
177 .to_string();
178
179 trace!(bytes = file_bytes.len(), file_name = %file_name, "Prepared parser upload");
180
181 let url = self.url.clone();
182 let key = self.key.clone();
183 let config = self.http_config.clone();
184 let tool_type = self.tool_type.clone();
185 let file_type = self.file_type.clone();
186 let response = send_multipart_request(reqwest::Method::POST, url, key, config, move || {
187 let file_part = reqwest::multipart::Part::bytes(file_bytes.clone())
188 .file_name(file_name.clone())
189 .mime_str("application/octet-stream")?;
190 Ok(reqwest::multipart::Form::new()
191 .part("file", file_part)
192 .text("tool_type", format!("{:?}", tool_type).to_lowercase())
193 .text("file_type", format!("{:?}", file_type)))
194 })
195 .await
196 .map_err(|e| e.context("file parser create"))?;
197
198 let create_response =
199 parse_typed_response::<FileParserCreateResponse>(response)
200 .await
201 .map_err(|e| e.context("file parser create"))?;
202
203 debug!(task_id = %create_response.task_id, "File parser task created");
204
205 if !create_response.is_success() {
206 warn!(
207 message = %create_response.message,
208 "File parser task creation rejected by server"
209 );
210 return Err(crate::client::error::ZaiError::ApiError {
211 code: codes::SDK_EXTERNAL_TOOL,
212 message: format!("Task creation failed: {}", create_response.message),
213 });
214 }
215
216 Ok(create_response)
217 }
218}