gproxy_protocol/adapt/generate/resources/
responses.rs1use super::*;
2use crate::wire::{DeclaredFields, openai::responses as r};
3
4impl<R: ResourceAccess> GenerationResources<'_, R> {
5 pub async fn responses(
6 &self,
7 input: r::GenerateContentRequestBody,
8 ) -> Result<r::GenerateContentRequestBody, TransformError> {
9 let mut input = input.into_declared();
10 let mut budget = self.budget();
11 if let Some(r::Input::Items(items)) = &mut input.input {
12 for item in items {
13 match item {
14 r::InputItem::Message(message) => {
15 for part in &mut message.content {
16 budget.input_part(part).await?;
17 }
18 }
19 r::InputItem::Easy(message) => {
20 if let r::MessageContent::Parts(parts) = &mut message.content {
21 for part in parts {
22 budget.input_part(part).await?;
23 }
24 }
25 }
26 r::InputItem::FunctionCallOutput(output) => {
27 if let r::FunctionOutput::Content(parts) = &mut output.output {
28 for part in parts {
29 budget.function_part(part).await?;
30 }
31 }
32 }
33 r::InputItem::CustomToolCallOutput(output) => {
34 if let r::CustomOutput::Content(parts) = &mut output.output {
35 for part in parts {
36 budget.input_part(part).await?;
37 }
38 }
39 }
40 _ => {}
41 }
42 }
43 }
44 Ok(input)
45 }
46}
47
48impl<R: ResourceAccess> Budget<'_, '_, R> {
49 async fn input_part(&mut self, part: &mut r::InputContent) -> Result<(), TransformError> {
50 match part {
51 r::InputContent::Image(image) => {
52 let id = image.file_id.as_ref().and_then(|v| v.as_ref());
53 let url = image.image_url.as_ref().and_then(|v| v.as_ref());
54 if id.is_some() && url.is_some() {
55 return Err(TransformError::shape(
56 "input_image",
57 "ambiguous native ID and URL",
58 ));
59 }
60 let reference = if let Some(id) = id {
61 ResourceReference::Id(id.clone())
62 } else if let Some(url) = url {
63 if url.starts_with("data:") {
64 return Ok(());
65 }
66 ResourceReference::Url(url.clone())
67 } else {
68 return Ok(());
69 };
70 let media = self.read(reference, true).await?;
71 image.image_url = Some(Some(media.data_uri()));
72 image.file_id = None;
73 }
74 r::InputContent::File(file) => {
75 let id = file.file_id.as_ref().and_then(|v| v.as_ref());
76 let url = file.file_url.as_ref();
77 if usize::from(id.is_some())
78 + usize::from(url.is_some())
79 + usize::from(file.file_data.is_some())
80 > 1
81 {
82 return Err(TransformError::shape(
83 "input_file",
84 "ambiguous file representations",
85 ));
86 }
87 let reference = if let Some(id) = id {
88 ResourceReference::Id(id.clone())
89 } else if let Some(url) = url {
90 ResourceReference::Url(url.clone())
91 } else {
92 return Ok(());
93 };
94 let media = self.read(reference, false).await?;
95 file.file_data = Some(media.data_uri());
96 file.file_id = None;
97 file.file_url = None;
98 if file.filename.is_none() {
99 file.filename = media.filename;
100 }
101 }
102 r::InputContent::Text(_) => {}
103 }
104 Ok(())
105 }
106}
107
108impl<R: ResourceAccess> Budget<'_, '_, R> {
109 async fn function_part(
110 &mut self,
111 part: &mut r::FunctionOutputContent,
112 ) -> Result<(), TransformError> {
113 match part {
114 r::FunctionOutputContent::Image(image) => {
115 let id = image.file_id.as_ref().and_then(|v| v.as_ref());
116 let url = image.image_url.as_ref().and_then(|v| v.as_ref());
117 if id.is_some() && url.is_some() {
118 return Err(TransformError::shape(
119 "function_output.image",
120 "ambiguous native ID and URL",
121 ));
122 }
123 let reference = if let Some(id) = id {
124 ResourceReference::Id(id.clone())
125 } else if let Some(url) = url {
126 if url.starts_with("data:") {
127 return Ok(());
128 }
129 ResourceReference::Url(url.clone())
130 } else {
131 return Ok(());
132 };
133 let media = self.read(reference, true).await?;
134 image.image_url = Some(Some(media.data_uri()));
135 image.file_id = None;
136 }
137 r::FunctionOutputContent::File(file) => {
138 let id = file.file_id.as_ref().and_then(|v| v.as_ref());
139 let url = file.file_url.as_ref().and_then(|v| v.as_ref());
140 let data = file.file_data.as_ref().and_then(|v| v.as_ref());
141 if usize::from(id.is_some())
142 + usize::from(url.is_some())
143 + usize::from(data.is_some())
144 > 1
145 {
146 return Err(TransformError::shape(
147 "function_output.file",
148 "ambiguous file representations",
149 ));
150 }
151 let reference = if let Some(id) = id {
152 ResourceReference::Id(id.clone())
153 } else if let Some(url) = url {
154 ResourceReference::Url(url.clone())
155 } else {
156 return Ok(());
157 };
158 let media = self.read(reference, false).await?;
159 file.file_data = Some(Some(media.data_uri()));
160 file.file_id = None;
161 file.file_url = None;
162 if file.filename.as_ref().is_none_or(|v| v.is_none()) {
163 file.filename = media.filename.map(Some);
164 }
165 }
166 r::FunctionOutputContent::Text(_) => {}
167 }
168 Ok(())
169 }
170}