feat: support file delete api (#45)
This commit is contained in:
parent
ffa57e420f
commit
838c847d6c
10 changed files with 113 additions and 26 deletions
|
|
@ -33,6 +33,7 @@ import ai.z.openapi.core.model.FlowableClientResponse;
|
|||
import ai.z.openapi.utils.FlowableRequestSupplier;
|
||||
import ai.z.openapi.utils.OkHttps;
|
||||
import ai.z.openapi.utils.RequestSupplier;
|
||||
import ai.z.openapi.utils.StringUtils;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
|
@ -318,7 +319,9 @@ public abstract class AbstractAiClient extends AbstractClientBaseService {
|
|||
tResp.setMsg("Call Failed");
|
||||
tResp.setSuccess(false);
|
||||
ChatError chatError = new ChatError();
|
||||
chatError.setCode(Integer.parseInt(e.code));
|
||||
if (StringUtils.isNotEmpty(e.code)) {
|
||||
chatError.setCode(Integer.parseInt(e.code));
|
||||
}
|
||||
chatError.setMessage(e.getMessage());
|
||||
tResp.setError(chatError);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,15 +31,6 @@ public interface FileApi {
|
|||
@POST("files")
|
||||
Single<File> uploadFile(@Body MultipartBody multipartBody);
|
||||
|
||||
/**
|
||||
* Retrieve file metadata and information Gets detailed information about a previously
|
||||
* uploaded file
|
||||
* @param fileId Unique identifier of the file to retrieve
|
||||
* @return File metadata including name, size, purpose, and creation time
|
||||
*/
|
||||
@GET("files/{file_id}")
|
||||
Single<File> retrieveFile(@Path("file_id") String fileId);
|
||||
|
||||
/**
|
||||
* Delete a file from the platform Permanently removes the file and all associated
|
||||
* data
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import ai.z.openapi.service.model.ZAiHttpException;
|
|||
import ai.z.openapi.utils.FlowableRequestSupplier;
|
||||
import ai.z.openapi.utils.RequestSupplier;
|
||||
import ai.z.openapi.utils.StringUtils;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.reactivex.rxjava3.core.BackpressureStrategy;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
|
|
@ -117,10 +118,41 @@ public abstract class AbstractClientBaseService {
|
|||
if (StringUtils.isEmpty(errorBody)) {
|
||||
throw e;
|
||||
}
|
||||
ZAiError error = mapper.readValue(errorBody, ZAiError.class);
|
||||
throw new ZAiHttpException(error, e, e.code());
|
||||
// here not only the ZAiError, also has {"error": "message"} and others
|
||||
JsonNode jsonNode = mapper.readTree(errorBody);
|
||||
if (jsonNode.has("error")) {
|
||||
JsonNode errorNode = jsonNode.get("error");
|
||||
if (errorNode.isTextual()) {
|
||||
JsonNode codeNode = jsonNode.get("code");
|
||||
throw new ZAiHttpException(errorNode.asText(), codeNode == null ? null : codeNode.asText(), e,
|
||||
e.code());
|
||||
}
|
||||
else {
|
||||
ZAiError error = mapper.readValue(errorBody, ZAiError.class);
|
||||
throw new ZAiHttpException(error, e, e.code());
|
||||
}
|
||||
}
|
||||
else if (jsonNode.has("msg")) {
|
||||
JsonNode msgNode = jsonNode.get("msg");
|
||||
JsonNode codeNode = jsonNode.get("code");
|
||||
throw new ZAiHttpException(msgNode.asText(), codeNode == null ? null : codeNode.asText(), e,
|
||||
e.code());
|
||||
}
|
||||
else if (jsonNode.has("message")) {
|
||||
JsonNode msgNode = jsonNode.get("message");
|
||||
JsonNode codeNode = jsonNode.get("code");
|
||||
throw new ZAiHttpException(msgNode.asText(), codeNode == null ? null : codeNode.asText(), e,
|
||||
e.code());
|
||||
}
|
||||
else {
|
||||
throw new ZAiHttpException(errorBody, null, e, e.code());
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
catch (ZAiHttpException zAiHttpException) {
|
||||
throw zAiHttpException;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error(ex.getMessage(), ex);
|
||||
// couldn't parse ZAiError error
|
||||
throw e;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
package ai.z.openapi.service.file;
|
||||
|
||||
import ai.z.openapi.core.model.ClientRequest;
|
||||
import ai.z.openapi.core.model.ClientResponse;
|
||||
import ai.z.openapi.service.batches.BatchRequest;
|
||||
import ai.z.openapi.service.model.ChatError;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Data
|
||||
@Builder
|
||||
public class FileDelRequest implements ClientRequest<FileDelRequest> {
|
||||
|
||||
private String fileId;
|
||||
|
||||
}
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
package ai.z.openapi.service.file;
|
||||
|
||||
import ai.z.openapi.core.model.ClientResponse;
|
||||
import ai.z.openapi.service.model.ChatError;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileDelResponse {
|
||||
public class FileDelResponse implements ClientResponse<FileDeleted> {
|
||||
|
||||
private int code;
|
||||
|
||||
|
|
@ -13,4 +15,6 @@ public class FileDelResponse {
|
|||
|
||||
private FileDeleted data;
|
||||
|
||||
private ChatError error;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,13 @@ public interface FileService {
|
|||
*/
|
||||
FileApiResponse uploadFile(FileUploadParams request);
|
||||
|
||||
/**
|
||||
* Delete file by file ID.
|
||||
* @param request the file id to delete.
|
||||
* @return FileDelResponse containing the delete result
|
||||
*/
|
||||
FileDelResponse deleteFile(FileDelRequest request);
|
||||
|
||||
/**
|
||||
* Lists all files.
|
||||
* @param queryFilesRequest FileListParams containing the query parameters for listing
|
||||
|
|
|
|||
|
|
@ -70,6 +70,12 @@ public class FileServiceImpl implements FileService {
|
|||
return this.zAiClient.executeRequest(request, supplier, FileApiResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileDelResponse deleteFile(FileDelRequest request) {
|
||||
RequestSupplier<FileDelRequest, FileDeleted> supplier = (params -> fileApi.deletedFile(params.getFileId()));
|
||||
return this.zAiClient.executeRequest(request, supplier, FileDelResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryFileApiResponse listFiles(FileListParams queryFilesRequest) {
|
||||
RequestSupplier<FileListParams, QueryFileResult> supplier = (params) -> fileApi.queryFileList(params.getAfter(),
|
||||
|
|
|
|||
|
|
@ -30,12 +30,8 @@ public class ZAiError {
|
|||
*/
|
||||
String message;
|
||||
|
||||
String type;
|
||||
|
||||
String param;
|
||||
|
||||
/**
|
||||
* ZAI error code, for example "invalid_api_key"
|
||||
* ZAI error code, for example "401"
|
||||
*/
|
||||
String code;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,23 +8,27 @@ public class ZAiHttpException extends RuntimeException {
|
|||
public final int statusCode;
|
||||
|
||||
/**
|
||||
* ZAI error code, for example "invalid_api_key"
|
||||
* ZAI error code, for example "1233"
|
||||
*/
|
||||
public final String code;
|
||||
|
||||
public final String param;
|
||||
|
||||
/**
|
||||
* ZAI error type, for example "invalid_request_error"
|
||||
* ZAI error message
|
||||
*/
|
||||
public final String type;
|
||||
public final String msg;
|
||||
|
||||
public ZAiHttpException(ZAiError error, Exception parent, int statusCode) {
|
||||
super(error.error.message, parent);
|
||||
this.statusCode = statusCode;
|
||||
this.code = error.error.code;
|
||||
this.param = error.error.param;
|
||||
this.type = error.error.type;
|
||||
this.msg = error.error.message;
|
||||
}
|
||||
|
||||
public ZAiHttpException(String errorMsg, String errorCode, Exception parent, int statusCode) {
|
||||
super(errorMsg, parent);
|
||||
this.statusCode = statusCode;
|
||||
this.code = errorCode;
|
||||
this.msg = errorMsg;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,6 +174,26 @@ public class FileServiceTest {
|
|||
logger.info("List files response: {}", mapper.writeValueAsString(response));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test Delete File - Basic Functionality")
|
||||
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
||||
void testDeleteFile() throws JsonProcessingException {
|
||||
|
||||
String fileId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
|
||||
FileDelRequest request = FileDelRequest.builder().fileId(fileId).build();
|
||||
|
||||
// Execute test
|
||||
FileDelResponse response = fileService.deleteFile(request);
|
||||
|
||||
// Verify results
|
||||
assertNotNull(response, "Response should not be null");
|
||||
assertFalse(response.isSuccess(), "Response should be failed");
|
||||
assertNull(response.getData(), "Response data should not be null");
|
||||
assertNotNull(response.getError(), "Response error should be null");
|
||||
|
||||
logger.info("Delete file response: {}", mapper.writeValueAsString(response));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test List Files with Purpose Filter")
|
||||
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
||||
|
|
|
|||
Loading…
Reference in a new issue