diff --git a/src/api/responses.rs b/src/api/responses.rs index 462b9b5..3d0253b 100644 --- a/src/api/responses.rs +++ b/src/api/responses.rs @@ -80,33 +80,49 @@ fn extract_responses_input( text_items } } else { - // Normal input extraction (existing logic) - items + // Normal input extraction + // First try: flat content parts (input_text / input_image) + let flat_text: String = items .iter() - .rev() - .find(|item| item["role"].as_str() == Some("user")) - .and_then(|item| { - // Also scan content array for images - if image.is_none() { - image = super::util::extract_first_image(&item["content"]); - } - match &item["content"] { - serde_json::Value::String(s) => Some(s.clone()), - serde_json::Value::Array(parts) => Some( - parts - .iter() - .filter(|p| { - let t = p["type"].as_str().unwrap_or(""); - t == "input_text" || t == "text" - }) - .filter_map(|p| p["text"].as_str()) - .collect::>() - .join(" "), - ), - _ => None, - } + .filter(|item| { + let t = item["type"].as_str().unwrap_or(""); + t == "input_text" || t == "text" }) - .unwrap_or_default() + .filter_map(|p| p["text"].as_str()) + .collect::>() + .join(" "); + + if !flat_text.is_empty() { + flat_text + } else { + // Fallback: conversation-style with role: "user" + items + .iter() + .rev() + .find(|item| item["role"].as_str() == Some("user")) + .and_then(|item| { + // Also scan content array for images + if image.is_none() { + image = super::util::extract_first_image(&item["content"]); + } + match &item["content"] { + serde_json::Value::String(s) => Some(s.clone()), + serde_json::Value::Array(parts) => Some( + parts + .iter() + .filter(|p| { + let t = p["type"].as_str().unwrap_or(""); + t == "input_text" || t == "text" + }) + .filter_map(|p| p["text"].as_str()) + .collect::>() + .join(" "), + ), + _ => None, + } + }) + .unwrap_or_default() + } } } _ => String::new(), diff --git a/src/mitm/proxy.rs b/src/mitm/proxy.rs index 796d8b9..89787e3 100644 --- a/src/mitm/proxy.rs +++ b/src/mitm/proxy.rs @@ -633,6 +633,16 @@ async fn handle_http_over_tls( }; // Forward the request — if write fails, reconnect and retry once + // DEBUG: dump headers and total size + if req_path.contains("streamGenerateContent") { + let hdr_end = find_headers_end(&request_buf).unwrap_or(request_buf.len()); + let hdr_str = String::from_utf8_lossy(&request_buf[..hdr_end.min(request_buf.len())]); + info!( + total_buf_len = request_buf.len(), + body_len = request_buf.len() - hdr_end, + "MITM: sending request to upstream\n{hdr_str}" + ); + } if let Err(e) = conn.write_all(&request_buf).await { debug!(domain, error = %e, "MITM: upstream write failed, reconnecting"); let c = connect_upstream(domain, &upstream_config).await?;