use crate::{transform::generate::signature, wire::gemini as g};
pub(crate) fn is_run_part(part: &g::Part) -> bool {
part.thought == Some(true)
&& (part.text.is_some() || part.thought_signature.is_some())
&& part.function_call.is_none()
&& part.function_response.is_none()
&& part.inline_data.is_none()
&& part.file_data.is_none()
&& part.executable_code.is_none()
&& part.code_execution_result.is_none()
}
pub(crate) fn is_empty_text(part: &g::Part) -> bool {
part.thought != Some(true)
&& part.text.as_deref() == Some("")
&& part.thought_signature.is_none()
&& part.function_call.is_none()
&& part.function_response.is_none()
&& part.inline_data.is_none()
&& part.file_data.is_none()
&& part.executable_code.is_none()
&& part.code_execution_result.is_none()
}
pub(crate) fn call_signature(part: &g::Part) -> Option<String> {
part.function_call
.as_ref()
.and(part.thought_signature.as_deref())
.map(signature::gemini_next)
}
pub fn without_gemini_thinking(body: &[u8]) -> Option<Vec<u8>> {
let needles = [signature::GEMINI, signature::GEMINI_NEXT].map(str::as_bytes);
if !needles
.iter()
.any(|needle| body.windows(needle.len()).any(|window| window == *needle))
{
return None;
}
let mut value: serde_json::Value = serde_json::from_slice(body).ok()?;
let messages = value.get_mut("messages")?.as_array_mut()?;
let mut changed = false;
for message in messages.iter_mut() {
let Some(content) = message
.get_mut("content")
.and_then(serde_json::Value::as_array_mut)
else {
continue;
};
let before = content.len();
content.retain(|block| {
block.get("type").and_then(serde_json::Value::as_str) != Some("thinking")
|| !block
.get("signature")
.and_then(serde_json::Value::as_str)
.is_some_and(signature::is_gemini)
});
changed |= content.len() != before;
}
if !changed {
return None;
}
messages.retain(|message| {
message
.get("content")
.and_then(serde_json::Value::as_array)
.is_none_or(|content| !content.is_empty())
});
serde_json::to_vec(&value).ok()
}