gproxy_protocol/transform/generate/chat_responses/response/
facts.rs1use super::ChatUsageSupplement;
2use crate::{
3 transform::TransformError,
4 wire::{
5 DeclaredFields,
6 openai::responses::{generate as g, input as i, response as r},
7 },
8};
9
10#[derive(Debug)]
15pub struct ResponsesResponseContext {
16 pub request: g::GenerateContentRequestBody,
17 pub effective_parallel_tool_calls: bool,
18 pub effective_tool_choice: i::ToolChoice,
19 pub usage: ChatUsageSupplement,
20 pub effective_prompt_cache_options: Option<r::ResponsePromptCacheOptions>,
21}
22
23impl ResponsesResponseContext {
24 pub(crate) fn into_response(
25 self,
26 id: String,
27 created_at: i64,
28 model: String,
29 ) -> Result<r::GenerateContentResponseBody, TransformError> {
30 let request = self.request.into_declared();
31 let choice = self.effective_tool_choice.into_declared();
32 if request
33 .parallel_tool_calls
34 .flatten()
35 .is_some_and(|v| v != self.effective_parallel_tool_calls)
36 || request.tool_choice.as_ref().is_some_and(|v| v != &choice)
37 {
38 return Err(TransformError::shape(
39 "response_context",
40 "effective settings contradict original request",
41 ));
42 }
43 let conversation = request.conversation.map(|value| {
44 value.map(|value| match value {
45 i::ConversationParam::Id(id) => i::ResponseConversationParam {
46 id,
47 rest: Default::default(),
48 },
49 i::ConversationParam::Object(value) => value,
50 })
51 });
52 let cache = self.effective_prompt_cache_options.into_declared();
53 if let Some(requested) = request.prompt_cache_options {
54 let actual = cache
55 .as_ref()
56 .ok_or_else(|| TransformError::missing_metadata("response.prompt_cache_options"))?;
57 if requested.mode.is_some_and(|v| v != actual.mode)
58 || requested.ttl.is_some_and(|v| v != actual.ttl)
59 {
60 return Err(TransformError::shape(
61 "response.prompt_cache_options",
62 "effective cache settings contradict request",
63 ));
64 }
65 }
66 Ok(r::GenerateContentResponseBody {
67 access_programs: None,
68 prompt_cache_diagnostics: None,
69 id,
70 created_at,
71 model,
72 object: r::ResponseObject::Response,
73 error: None,
74 incomplete_details: None,
75 instructions: request.instructions.flatten().map(i::Input::Text),
76 metadata: request.metadata.flatten(),
77 output: Vec::new(),
78 parallel_tool_calls: self.effective_parallel_tool_calls,
79 temperature: request.temperature.flatten(),
80 tool_choice: choice,
81 tools: request.tools.unwrap_or_default(),
82 top_p: request.top_p.flatten(),
83 background: request.background,
84 completed_at: None,
85 conversation,
86 max_output_tokens: request.max_output_tokens,
87 max_tool_calls: request.max_tool_calls,
88 moderation: None,
89 output_text: None,
90 previous_response_id: request.previous_response_id,
91 prompt: request.prompt,
92 prompt_cache_key: request.prompt_cache_key,
93 prompt_cache_options: cache,
94 prompt_cache_retention: request.prompt_cache_retention,
95 reasoning: request.reasoning,
96 safety_identifier: request.safety_identifier,
97 service_tier: None,
98 status: None,
99 text: request.text,
100 top_logprobs: request.top_logprobs,
101 truncation: request.truncation,
102 usage: None,
103 user: request.user,
104 rest: Default::default(),
105 })
106 }
107}