use bamboo_agent_core::MessagePart;
pub(super) fn summarize_image_url(url: &str) -> String {
let trimmed = url.trim();
if trimmed.starts_with("data:") {
let mut mime = "unknown".to_string();
if let Some(semi_idx) = trimmed.find(';') {
let header = &trimmed["data:".len()..semi_idx];
if !header.trim().is_empty() {
mime = header.trim().to_string();
}
}
let approx_bytes = trimmed
.split_once(',')
.map(|(_, data)| {
let len = data.trim().len();
(len.saturating_mul(3)) / 4
})
.unwrap_or(0);
return format!("{mime} (~{approx_bytes} bytes)");
}
const MAX: usize = 120;
if trimmed.len() <= MAX {
trimmed.to_string()
} else {
format!("{}...", &trimmed[..MAX])
}
}
pub(super) fn rewrite_parts_to_placeholder(parts: &[MessagePart]) -> String {
let mut out = String::new();
for part in parts {
match part {
MessagePart::Text { text } => out.push_str(text),
MessagePart::ImageUrl { image_url } => {
let summary = summarize_image_url(&image_url.url);
out.push_str("\n[Image omitted: ");
out.push_str(&summary);
out.push_str("]\n");
}
}
}
out
}
#[cfg(any(test, windows))]
pub(super) fn persistable_image_urls(parts: &[MessagePart]) -> Vec<String> {
parts
.iter()
.filter_map(|p| match p {
MessagePart::ImageUrl { image_url } => {
let trimmed = image_url.url.trim();
if trimmed.starts_with("data:") || trimmed.is_empty() {
None
} else {
Some(trimmed.to_string())
}
}
_ => None,
})
.collect()
}