gproxy_protocol/adapt/generate/resources/
gemini.rs1use super::*;
2use crate::wire::{DeclaredFields, gemini as g};
3
4impl<R: ResourceAccess> GenerationResources<'_, R> {
5 pub async fn gemini(
6 &self,
7 input: g::GenerateContentRequestBody,
8 ) -> Result<g::GenerateContentRequestBody, TransformError> {
9 let mut input = input.into_declared();
10 let mut budget = self.budget(crate::Dialect::Gemini);
11 for content in input
12 .contents
13 .iter_mut()
14 .chain(input.system_instruction.iter_mut())
15 {
16 for part in content.parts.iter_mut().flatten() {
17 if let Some(file) = &part.file_data {
18 if part.inline_data.is_some() {
19 return Err(TransformError::shape(
20 "part",
21 "ambiguous file and inline data",
22 ));
23 }
24 let image = file
25 .mime_type
26 .as_deref()
27 .is_some_and(|mime| mime.starts_with("image/"));
28 let Some(media) = budget
29 .read(ResourceReference::Url(file.file_uri.clone()), image)
30 .await?
31 else {
32 continue;
33 };
34 if file
35 .mime_type
36 .as_ref()
37 .is_some_and(|mime| mime != &media.mime)
38 {
39 return Err(TransformError::invalid_result(
40 "file_data.mime",
41 "resource MIME differs from request",
42 ));
43 }
44 part.inline_data =
45 Some(g::Blob::builder(media.mime, STANDARD.encode(media.bytes)).build());
46 part.file_data = None;
47 }
48 }
49 }
50 Ok(input)
51 }
52}