openai_oxide/resources/
files.rs1use crate::client::OpenAI;
4use crate::error::OpenAIError;
5use crate::types::file::{FileDeleted, FileList, FileObject, FileUploadParams};
6
7pub struct Files<'a> {
9 client: &'a OpenAI,
10}
11
12impl<'a> Files<'a> {
13 pub(crate) fn new(client: &'a OpenAI) -> Self {
14 Self { client }
15 }
16
17 pub async fn create(&self, params: FileUploadParams) -> Result<FileObject, OpenAIError> {
21 let form = reqwest::multipart::Form::new()
22 .part(
23 "file",
24 reqwest::multipart::Part::bytes(params.file).file_name(params.filename),
25 )
26 .text("purpose", params.purpose);
27
28 self.client.post_multipart("/files", form).await
29 }
30
31 pub async fn list(&self) -> Result<FileList, OpenAIError> {
35 self.client.get("/files").await
36 }
37
38 pub async fn retrieve(&self, file_id: &str) -> Result<FileObject, OpenAIError> {
42 self.client.get(&format!("/files/{file_id}")).await
43 }
44
45 pub async fn delete(&self, file_id: &str) -> Result<FileDeleted, OpenAIError> {
49 self.client.delete(&format!("/files/{file_id}")).await
50 }
51
52 pub async fn content(&self, file_id: &str) -> Result<bytes::Bytes, OpenAIError> {
56 self.client
57 .get_raw(&format!("/files/{file_id}/content"))
58 .await
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use crate::OpenAI;
65 use crate::config::ClientConfig;
66 use crate::types::file::FileUploadParams;
67
68 #[tokio::test]
69 async fn test_files_create() {
70 let mut server = mockito::Server::new_async().await;
71 let mock = server
72 .mock("POST", "/files")
73 .match_header("authorization", "Bearer sk-test")
74 .with_status(200)
75 .with_header("content-type", "application/json")
76 .with_body(
77 r#"{
78 "id": "file-abc123",
79 "object": "file",
80 "bytes": 120000,
81 "created_at": 1677610602,
82 "filename": "data.jsonl",
83 "purpose": "fine-tune",
84 "status": "uploaded"
85 }"#,
86 )
87 .create_async()
88 .await;
89
90 let client = OpenAI::with_config(ClientConfig::new("sk-test").base_url(server.url()));
91 let params = FileUploadParams::new(b"test data".to_vec(), "data.jsonl", "fine-tune");
92
93 let response = client.files().create(params).await.unwrap();
94 assert_eq!(response.id, "file-abc123");
95 assert_eq!(response.purpose, "fine-tune");
96 mock.assert_async().await;
97 }
98
99 #[tokio::test]
100 async fn test_files_list() {
101 let mut server = mockito::Server::new_async().await;
102 let mock = server
103 .mock("GET", "/files")
104 .with_status(200)
105 .with_header("content-type", "application/json")
106 .with_body(
107 r#"{
108 "object": "list",
109 "data": [{
110 "id": "file-abc123",
111 "object": "file",
112 "bytes": 120000,
113 "created_at": 1677610602,
114 "filename": "data.jsonl",
115 "purpose": "fine-tune",
116 "status": "processed"
117 }]
118 }"#,
119 )
120 .create_async()
121 .await;
122
123 let client = OpenAI::with_config(ClientConfig::new("sk-test").base_url(server.url()));
124 let response = client.files().list().await.unwrap();
125 assert_eq!(response.data.len(), 1);
126 mock.assert_async().await;
127 }
128
129 #[tokio::test]
130 async fn test_files_retrieve() {
131 let mut server = mockito::Server::new_async().await;
132 let mock = server
133 .mock("GET", "/files/file-abc123")
134 .with_status(200)
135 .with_header("content-type", "application/json")
136 .with_body(
137 r#"{
138 "id": "file-abc123",
139 "object": "file",
140 "bytes": 120000,
141 "created_at": 1677610602,
142 "filename": "data.jsonl",
143 "purpose": "fine-tune",
144 "status": "processed"
145 }"#,
146 )
147 .create_async()
148 .await;
149
150 let client = OpenAI::with_config(ClientConfig::new("sk-test").base_url(server.url()));
151 let file = client.files().retrieve("file-abc123").await.unwrap();
152 assert_eq!(file.id, "file-abc123");
153 mock.assert_async().await;
154 }
155
156 #[tokio::test]
157 async fn test_files_delete() {
158 let mut server = mockito::Server::new_async().await;
159 let mock = server
160 .mock("DELETE", "/files/file-abc123")
161 .with_status(200)
162 .with_header("content-type", "application/json")
163 .with_body(r#"{"id": "file-abc123", "object": "file", "deleted": true}"#)
164 .create_async()
165 .await;
166
167 let client = OpenAI::with_config(ClientConfig::new("sk-test").base_url(server.url()));
168 let resp = client.files().delete("file-abc123").await.unwrap();
169 assert!(resp.deleted);
170 mock.assert_async().await;
171 }
172
173 #[tokio::test]
174 async fn test_files_content() {
175 let mut server = mockito::Server::new_async().await;
176 let content_bytes = b"line1\nline2\nline3";
177 let mock = server
178 .mock("GET", "/files/file-abc123/content")
179 .with_status(200)
180 .with_header("content-type", "application/octet-stream")
181 .with_body(content_bytes)
182 .create_async()
183 .await;
184
185 let client = OpenAI::with_config(ClientConfig::new("sk-test").base_url(server.url()));
186 let response = client.files().content("file-abc123").await.unwrap();
187 assert_eq!(response.as_ref(), content_bytes);
188 mock.assert_async().await;
189 }
190}