From 686f5820d66cdd3ab1692b4078d9d1c9ffe115ae Mon Sep 17 00:00:00 2001 From: Nikketryhard Date: Sat, 14 Feb 2026 04:09:41 -0600 Subject: [PATCH] refactor: extract ResponseData struct to eliminate 18-arg build_response_object --- src/api/responses.rs | 189 ++++++++++++++++++++++--------------------- 1 file changed, 96 insertions(+), 93 deletions(-) diff --git a/src/api/responses.rs b/src/api/responses.rs index a8073c8..a4b4b67 100644 --- a/src/api/responses.rs +++ b/src/api/responses.rs @@ -65,55 +65,51 @@ fn extract_conversation_id(conv: &Option) -> Option { } } -/// Build a full Response object matching the official OpenAI schema. -fn build_response_object( - id: &str, - model: &str, +/// Response-specific data for building a Response object. +struct ResponseData { + id: String, + model: String, status: &'static str, created_at: u64, completed_at: Option, output: Vec, usage: Option, - instructions: Option<&str>, - store: bool, - temperature: f64, - top_p: f64, - max_output_tokens: Option, - previous_response_id: Option<&str>, - user: Option<&str>, - metadata: &serde_json::Value, thinking_signature: Option, thinking: Option, thinking_duration: Option, -) -> 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 { - id: id.to_string(), + id: data.id, object: "response", - created_at, - status, - completed_at, + created_at: data.created_at, + status: data.status, + completed_at: data.completed_at, error: None, incomplete_details: None, - instructions: instructions.map(|s| s.to_string()), - max_output_tokens, - model: model.to_string(), - output, + instructions: params.instructions.clone(), + max_output_tokens: params.max_output_tokens, + model: data.model, + output: data.output, 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(), - store, - temperature, + store: params.store, + temperature: params.temperature, text: TextFormat::default(), tool_choice: "auto", tools: vec![], - top_p, + top_p: params.top_p, truncation: "disabled", - usage, - user: user.map(|s| s.to_string()), - metadata: metadata.clone(), - thinking_signature, - thinking, - thinking_duration, + usage: data.usage, + user: params.user.clone(), + metadata: params.metadata.clone(), + thinking_signature: data.thinking_signature, + thinking: data.thinking, + 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 resp = build_response_object( - &response_id, - &model_name, - "completed", - created_at, - Some(completed_at), - vec![ResponseOutput { - output_type: "message", - id: msg_id, + ResponseData { + id: response_id, + model: model_name, status: "completed", - role: "assistant", - content: vec![OutputContent { - content_type: "output_text", - text: poll_result.text, - annotations: vec![], + created_at, + completed_at: Some(completed_at), + output: vec![ResponseOutput { + output_type: "message", + id: msg_id, + status: "completed", + role: "assistant", + content: vec![OutputContent { + content_type: "output_text", + text: poll_result.text, + annotations: vec![], + }], }], - }], - Some(usage), - params.instructions.as_deref(), - params.store, - params.temperature, - params.top_p, - 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, + usage: Some(usage), + thinking_signature: poll_result.thinking_signature, + thinking: poll_result.thinking, + thinking_duration: poll_result.thinking_duration, + }, + ¶ms, ); Json(resp).into_response() @@ -393,13 +384,19 @@ async fn handle_responses_stream( // Build the in-progress response shell (no output yet) let in_progress_resp = build_response_object( - &response_id, &model_name, "in_progress", created_at, None, - vec![], None, - params.instructions.as_deref(), params.store, - params.temperature, params.top_p, - params.max_output_tokens, params.previous_response_id.as_deref(), - params.user.as_deref(), ¶ms.metadata, - None, None, None, + ResponseData { + id: response_id.clone(), + model: model_name.clone(), + status: "in_progress", + created_at, + completed_at: None, + output: vec![], + usage: None, + thinking_signature: None, + thinking: None, + thinking_duration: None, + }, + ¶ms, ); let resp_json = response_to_json(&in_progress_resp); @@ -544,13 +541,19 @@ async fn handle_responses_stream( // Timeout — emit incomplete response let timeout_resp = build_response_object( - &response_id, &model_name, "incomplete", created_at, None, - vec![], Some(Usage::estimate(¶ms.user_text, "")), - params.instructions.as_deref(), params.store, - params.temperature, params.top_p, - params.max_output_tokens, params.previous_response_id.as_deref(), - params.user.as_deref(), ¶ms.metadata, - None, None, None, + ResponseData { + id: response_id.clone(), + model: model_name.clone(), + status: "incomplete", + created_at, + completed_at: None, + output: vec![], + usage: Some(Usage::estimate(¶ms.user_text, "")), + thinking_signature: None, + thinking: None, + thinking_duration: None, + }, + ¶ms, ); yield Ok(responses_sse_event( "response.completed", @@ -578,6 +581,7 @@ async fn handle_responses_stream( /// 2. response.content_part.done /// 3. response.output_item.done /// 4. response.completed +#[allow(clippy::too_many_arguments)] fn completion_events( resp_id: &str, model: &str, @@ -609,30 +613,29 @@ fn completion_events( }); let completed_resp = build_response_object( - resp_id, model, "completed", created_at, Some(completed_at), - vec![ResponseOutput { - output_type: "message", - id: msg_id.to_string(), + ResponseData { + id: resp_id.to_string(), + model: model.to_string(), status: "completed", - role: "assistant", - content: vec![OutputContent { - content_type: "output_text", - text: text.to_string(), - annotations: vec![], + created_at, + completed_at: Some(completed_at), + output: vec![ResponseOutput { + output_type: "message", + id: msg_id.to_string(), + status: "completed", + role: "assistant", + content: vec![OutputContent { + content_type: "output_text", + text: text.to_string(), + annotations: vec![], + }], }], - }], - Some(usage), - params.instructions.as_deref(), - params.store, - params.temperature, - params.top_p, - params.max_output_tokens, - params.previous_response_id.as_deref(), - params.user.as_deref(), - ¶ms.metadata, - thinking_signature, - thinking, - thinking_duration, + usage: Some(usage), + thinking_signature, + thinking, + thinking_duration, + }, + params, ); vec![