Skip to main content

gproxy_protocol/transform/generate/chat_responses/
request.rs

1mod controls;
2mod history;
3mod media;
4mod messages;
5mod shared_controls;
6mod tools;
7use crate::{
8    transform::{Converted, Report, TransformError},
9    wire::openai::{chat, responses},
10};
11
12/// Exact declared call kind recovered from a previous response, never inferred from an ID prefix.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14pub enum ToolCallKind {
15    Function,
16    Custom,
17}
18
19pub fn chat_to_responses_request(
20    input: chat::GenerateContentRequestBody,
21    target_model: impl Into<String>,
22    flow: &mut crate::transform::identity::IdentityFlow,
23    policy: &crate::transform::identity::TargetIdPolicy,
24) -> Result<Converted<responses::GenerateContentRequestBody>, TransformError> {
25    chat_to_responses_request_with_calls(input, target_model, &Default::default(), flow, policy)
26}
27
28pub fn chat_to_responses_request_with_calls(
29    input: chat::GenerateContentRequestBody,
30    target_model: impl Into<String>,
31    prior_calls: &std::collections::BTreeMap<String, ToolCallKind>,
32    flow: &mut crate::transform::identity::IdentityFlow,
33    policy: &crate::transform::identity::TargetIdPolicy,
34) -> Result<Converted<responses::GenerateContentRequestBody>, TransformError> {
35    let mut ids = flow.clone();
36    let model = target_model.into();
37
38    let mut report = Report::default();
39    let mut output = responses::GenerateContentRequestBody::builder().build();
40    controls::to_responses(&input, &mut output, &mut report)?;
41    output.model = Some(model.clone());
42
43    output.tools = if let Some(functions) = input.functions {
44        Some(tools::legacy(functions)?)
45    } else {
46        input
47            .tools
48            .map(tools::to_responses)
49            .map(crate::transform::optional)
50            .transpose()?
51            .flatten()
52    };
53    output.tool_choice = if let Some(choice) = input.function_call {
54        Some(tools::legacy_choice(choice))
55    } else {
56        input
57            .tool_choice
58            .map(tools::choice_to_responses)
59            .map(crate::transform::optional)
60            .transpose()?
61            .flatten()
62    };
63    output.input = Some(responses::input::Input::Items(messages::to_responses(
64        input.messages,
65        prior_calls,
66        &mut report,
67        &mut ids,
68        policy,
69    )?));
70    output.metadata = input.metadata;
71    output.prompt_cache_key = input.prompt_cache_key;
72    output.safety_identifier = input.safety_identifier;
73    output.store = input.store;
74    output.stream = input.stream;
75    output.user = input.user;
76    crate::transform::instructions::responses(
77        &mut output.input,
78        &mut output.instructions,
79        &model,
80        &mut report,
81    );
82    *flow = ids;
83    crate::transform::generate::openai_controls::target_responses(&mut output, &mut report);
84    Ok(Converted {
85        value: output,
86        report,
87    })
88}
89
90pub fn responses_to_chat_request(
91    mut input: responses::GenerateContentRequestBody,
92    target_model: impl Into<String>,
93) -> Result<Converted<chat::GenerateContentRequestBody>, TransformError> {
94    let model = target_model.into();
95
96    let mut report = Report::default();
97    crate::transform::generate::openai_controls::project_request(&mut input, &mut report)?;
98    let bindings = super::client_tools::Bindings::new(&input)?;
99    bindings.lower(&mut input, &mut report)?;
100    let mut output = chat::GenerateContentRequestBody::builder(Vec::new(), model).build();
101    controls::to_chat(&input, &mut output, &mut report)?;
102    output.tools = input
103        .tools
104        .map(tools::to_chat)
105        .map(crate::transform::optional)
106        .transpose()?
107        .flatten();
108    output.tool_choice = input
109        .tool_choice
110        .map(|v| crate::transform::optional(tools::choice_to_chat(v)))
111        .transpose()?
112        .flatten();
113    if let Some(Some(text)) = input.instructions {
114        output.messages.push(chat::ChatMessage::System(
115            chat::SystemMessage::builder(chat::SystemRole::System, chat::TextContent::Text(text))
116                .build(),
117        ));
118    }
119    output
120        .messages
121        .extend(history::to_chat(input.input, &mut report)?);
122    output.metadata = input.metadata;
123    output.prompt_cache_key = input.prompt_cache_key;
124    output.safety_identifier = input.safety_identifier;
125    output.store = input.store;
126    output.stream = input.stream;
127    output.user = input.user;
128    crate::transform::instructions::chat(&mut output.messages, &output.model, &mut report);
129
130    crate::transform::generate::openai_controls::target_chat(&mut output, &mut report);
131    Ok(Converted {
132        value: output,
133        report,
134    })
135}