refactor: extract ResponseData struct to eliminate 18-arg build_response_object
This commit is contained in:
@@ -65,55 +65,51 @@ fn extract_conversation_id(conv: &Option<serde_json::Value>) -> Option<String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a full Response object matching the official OpenAI schema.
|
/// Response-specific data for building a Response object.
|
||||||
fn build_response_object(
|
struct ResponseData {
|
||||||
id: &str,
|
id: String,
|
||||||
model: &str,
|
model: String,
|
||||||
status: &'static str,
|
status: &'static str,
|
||||||
created_at: u64,
|
created_at: u64,
|
||||||
completed_at: Option<u64>,
|
completed_at: Option<u64>,
|
||||||
output: Vec<ResponseOutput>,
|
output: Vec<ResponseOutput>,
|
||||||
usage: Option<Usage>,
|
usage: Option<Usage>,
|
||||||
instructions: Option<&str>,
|
|
||||||
store: bool,
|
|
||||||
temperature: f64,
|
|
||||||
top_p: f64,
|
|
||||||
max_output_tokens: Option<u64>,
|
|
||||||
previous_response_id: Option<&str>,
|
|
||||||
user: Option<&str>,
|
|
||||||
metadata: &serde_json::Value,
|
|
||||||
thinking_signature: Option<String>,
|
thinking_signature: Option<String>,
|
||||||
thinking: Option<String>,
|
thinking: Option<String>,
|
||||||
thinking_duration: Option<String>,
|
thinking_duration: Option<String>,
|
||||||
) -> ResponsesResponse {
|
}
|
||||||
|
|
||||||
|
/// Build a full Response object matching the official OpenAI schema.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn build_response_object(data: ResponseData, params: &RequestParams) -> ResponsesResponse {
|
||||||
ResponsesResponse {
|
ResponsesResponse {
|
||||||
id: id.to_string(),
|
id: data.id,
|
||||||
object: "response",
|
object: "response",
|
||||||
created_at,
|
created_at: data.created_at,
|
||||||
status,
|
status: data.status,
|
||||||
completed_at,
|
completed_at: data.completed_at,
|
||||||
error: None,
|
error: None,
|
||||||
incomplete_details: None,
|
incomplete_details: None,
|
||||||
instructions: instructions.map(|s| s.to_string()),
|
instructions: params.instructions.clone(),
|
||||||
max_output_tokens,
|
max_output_tokens: params.max_output_tokens,
|
||||||
model: model.to_string(),
|
model: data.model,
|
||||||
output,
|
output: data.output,
|
||||||
parallel_tool_calls: true,
|
parallel_tool_calls: true,
|
||||||
previous_response_id: previous_response_id.map(|s| s.to_string()),
|
previous_response_id: params.previous_response_id.clone(),
|
||||||
reasoning: Reasoning::default(),
|
reasoning: Reasoning::default(),
|
||||||
store,
|
store: params.store,
|
||||||
temperature,
|
temperature: params.temperature,
|
||||||
text: TextFormat::default(),
|
text: TextFormat::default(),
|
||||||
tool_choice: "auto",
|
tool_choice: "auto",
|
||||||
tools: vec![],
|
tools: vec![],
|
||||||
top_p,
|
top_p: params.top_p,
|
||||||
truncation: "disabled",
|
truncation: "disabled",
|
||||||
usage,
|
usage: data.usage,
|
||||||
user: user.map(|s| s.to_string()),
|
user: params.user.clone(),
|
||||||
metadata: metadata.clone(),
|
metadata: params.metadata.clone(),
|
||||||
thinking_signature,
|
thinking_signature: data.thinking_signature,
|
||||||
thinking,
|
thinking: data.thinking,
|
||||||
thinking_duration,
|
thinking_duration: data.thinking_duration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,34 +336,29 @@ async fn handle_responses_sync(
|
|||||||
let usage = usage_from_poll(&state.mitm_store, &cascade_id, &poll_result.usage, ¶ms.user_text, &poll_result.text).await;
|
let usage = usage_from_poll(&state.mitm_store, &cascade_id, &poll_result.usage, ¶ms.user_text, &poll_result.text).await;
|
||||||
|
|
||||||
let resp = build_response_object(
|
let resp = build_response_object(
|
||||||
&response_id,
|
ResponseData {
|
||||||
&model_name,
|
id: response_id,
|
||||||
"completed",
|
model: model_name,
|
||||||
created_at,
|
|
||||||
Some(completed_at),
|
|
||||||
vec![ResponseOutput {
|
|
||||||
output_type: "message",
|
|
||||||
id: msg_id,
|
|
||||||
status: "completed",
|
status: "completed",
|
||||||
role: "assistant",
|
created_at,
|
||||||
content: vec![OutputContent {
|
completed_at: Some(completed_at),
|
||||||
content_type: "output_text",
|
output: vec![ResponseOutput {
|
||||||
text: poll_result.text,
|
output_type: "message",
|
||||||
annotations: vec![],
|
id: msg_id,
|
||||||
|
status: "completed",
|
||||||
|
role: "assistant",
|
||||||
|
content: vec![OutputContent {
|
||||||
|
content_type: "output_text",
|
||||||
|
text: poll_result.text,
|
||||||
|
annotations: vec![],
|
||||||
|
}],
|
||||||
}],
|
}],
|
||||||
}],
|
usage: Some(usage),
|
||||||
Some(usage),
|
thinking_signature: poll_result.thinking_signature,
|
||||||
params.instructions.as_deref(),
|
thinking: poll_result.thinking,
|
||||||
params.store,
|
thinking_duration: poll_result.thinking_duration,
|
||||||
params.temperature,
|
},
|
||||||
params.top_p,
|
¶ms,
|
||||||
params.max_output_tokens,
|
|
||||||
params.previous_response_id.as_deref(),
|
|
||||||
params.user.as_deref(),
|
|
||||||
¶ms.metadata,
|
|
||||||
poll_result.thinking_signature,
|
|
||||||
poll_result.thinking,
|
|
||||||
poll_result.thinking_duration,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Json(resp).into_response()
|
Json(resp).into_response()
|
||||||
@@ -393,13 +384,19 @@ async fn handle_responses_stream(
|
|||||||
|
|
||||||
// Build the in-progress response shell (no output yet)
|
// Build the in-progress response shell (no output yet)
|
||||||
let in_progress_resp = build_response_object(
|
let in_progress_resp = build_response_object(
|
||||||
&response_id, &model_name, "in_progress", created_at, None,
|
ResponseData {
|
||||||
vec![], None,
|
id: response_id.clone(),
|
||||||
params.instructions.as_deref(), params.store,
|
model: model_name.clone(),
|
||||||
params.temperature, params.top_p,
|
status: "in_progress",
|
||||||
params.max_output_tokens, params.previous_response_id.as_deref(),
|
created_at,
|
||||||
params.user.as_deref(), ¶ms.metadata,
|
completed_at: None,
|
||||||
None, None, None,
|
output: vec![],
|
||||||
|
usage: None,
|
||||||
|
thinking_signature: None,
|
||||||
|
thinking: None,
|
||||||
|
thinking_duration: None,
|
||||||
|
},
|
||||||
|
¶ms,
|
||||||
);
|
);
|
||||||
let resp_json = response_to_json(&in_progress_resp);
|
let resp_json = response_to_json(&in_progress_resp);
|
||||||
|
|
||||||
@@ -544,13 +541,19 @@ async fn handle_responses_stream(
|
|||||||
|
|
||||||
// Timeout — emit incomplete response
|
// Timeout — emit incomplete response
|
||||||
let timeout_resp = build_response_object(
|
let timeout_resp = build_response_object(
|
||||||
&response_id, &model_name, "incomplete", created_at, None,
|
ResponseData {
|
||||||
vec![], Some(Usage::estimate(¶ms.user_text, "")),
|
id: response_id.clone(),
|
||||||
params.instructions.as_deref(), params.store,
|
model: model_name.clone(),
|
||||||
params.temperature, params.top_p,
|
status: "incomplete",
|
||||||
params.max_output_tokens, params.previous_response_id.as_deref(),
|
created_at,
|
||||||
params.user.as_deref(), ¶ms.metadata,
|
completed_at: None,
|
||||||
None, None, None,
|
output: vec![],
|
||||||
|
usage: Some(Usage::estimate(¶ms.user_text, "")),
|
||||||
|
thinking_signature: None,
|
||||||
|
thinking: None,
|
||||||
|
thinking_duration: None,
|
||||||
|
},
|
||||||
|
¶ms,
|
||||||
);
|
);
|
||||||
yield Ok(responses_sse_event(
|
yield Ok(responses_sse_event(
|
||||||
"response.completed",
|
"response.completed",
|
||||||
@@ -578,6 +581,7 @@ async fn handle_responses_stream(
|
|||||||
/// 2. response.content_part.done
|
/// 2. response.content_part.done
|
||||||
/// 3. response.output_item.done
|
/// 3. response.output_item.done
|
||||||
/// 4. response.completed
|
/// 4. response.completed
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn completion_events(
|
fn completion_events(
|
||||||
resp_id: &str,
|
resp_id: &str,
|
||||||
model: &str,
|
model: &str,
|
||||||
@@ -609,30 +613,29 @@ fn completion_events(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let completed_resp = build_response_object(
|
let completed_resp = build_response_object(
|
||||||
resp_id, model, "completed", created_at, Some(completed_at),
|
ResponseData {
|
||||||
vec![ResponseOutput {
|
id: resp_id.to_string(),
|
||||||
output_type: "message",
|
model: model.to_string(),
|
||||||
id: msg_id.to_string(),
|
|
||||||
status: "completed",
|
status: "completed",
|
||||||
role: "assistant",
|
created_at,
|
||||||
content: vec![OutputContent {
|
completed_at: Some(completed_at),
|
||||||
content_type: "output_text",
|
output: vec![ResponseOutput {
|
||||||
text: text.to_string(),
|
output_type: "message",
|
||||||
annotations: vec![],
|
id: msg_id.to_string(),
|
||||||
|
status: "completed",
|
||||||
|
role: "assistant",
|
||||||
|
content: vec![OutputContent {
|
||||||
|
content_type: "output_text",
|
||||||
|
text: text.to_string(),
|
||||||
|
annotations: vec![],
|
||||||
|
}],
|
||||||
}],
|
}],
|
||||||
}],
|
usage: Some(usage),
|
||||||
Some(usage),
|
thinking_signature,
|
||||||
params.instructions.as_deref(),
|
thinking,
|
||||||
params.store,
|
thinking_duration,
|
||||||
params.temperature,
|
},
|
||||||
params.top_p,
|
params,
|
||||||
params.max_output_tokens,
|
|
||||||
params.previous_response_id.as_deref(),
|
|
||||||
params.user.as_deref(),
|
|
||||||
¶ms.metadata,
|
|
||||||
thinking_signature,
|
|
||||||
thinking,
|
|
||||||
thinking_duration,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
vec![
|
vec![
|
||||||
|
|||||||
Reference in New Issue
Block a user