use super::*;
pub(super) fn view_image_card(
state: &MissionControlState,
id: TranscriptCardId,
link: Option<TranscriptActivityLink>,
body: &str,
) -> TranscriptCard {
use crate::tools::contract::{arg_key, metadata_key};
let detail = link
.as_ref()
.and_then(|link| state.nodes.get(&link.activity_id))
.and_then(|node| node.tool_detail.as_ref());
let metadata = detail.map(|detail| &detail.metadata);
let status = detail
.map(|detail| transcript_status_from_activity(detail.status))
.or_else(|| {
link.as_ref()
.and_then(|link| state.nodes.get(&link.activity_id))
.map(|node| transcript_status_from_activity(node.status))
})
.unwrap_or_else(|| transcript_tool_status(state, id.entry_index));
let source_path = metadata
.and_then(|value| value.get(metadata_key::PATH))
.and_then(serde_json::Value::as_str)
.or_else(|| {
detail
.and_then(|detail| detail.params.get(arg_key::PATH))
.and_then(serde_json::Value::as_str)
});
let path = source_path.map(sanitized_single_line);
let mut card_metadata = Vec::new();
if let Some(provider) = metadata
.and_then(|value| value.get(metadata_key::PROVIDER))
.and_then(serde_json::Value::as_str)
{
card_metadata.push(format!("provider {}", sanitized_single_line(provider)));
}
if let Some(model) = metadata
.and_then(|value| value.get(metadata_key::MODEL))
.and_then(serde_json::Value::as_str)
{
card_metadata.push(format!("model {}", sanitized_single_line(model)));
}
if let Some(bytes) = metadata
.and_then(|value| value.get(metadata_key::IMAGE_BYTES))
.and_then(serde_json::Value::as_u64)
{
card_metadata.push(format!("{bytes} bytes"));
}
if let Some(chars) = metadata
.and_then(|value| value.get(metadata_key::PROMPT_CHARS))
.and_then(serde_json::Value::as_u64)
{
card_metadata.push(format!("prompt {chars} chars"));
}
if metadata
.and_then(|value| value.get(metadata_key::TRUNCATED))
.and_then(serde_json::Value::as_bool)
== Some(true)
{
card_metadata.push("response truncated".to_string());
}
let response = if status == TranscriptCardStatus::Success {
let source = detail
.map(|detail| detail.output.as_ref())
.filter(|output| !output.trim().is_empty())
.unwrap_or("");
bounded_preview_lines(source)
} else if matches!(
status,
TranscriptCardStatus::Failed | TranscriptCardStatus::Canceled
) {
let source = detail.map(|detail| detail.output.as_ref()).unwrap_or(body);
bounded_error_line(source)
} else {
String::new()
};
let title = if status == TranscriptCardStatus::Canceled {
"View Image • canceled"
} else {
"View Image"
};
if let Some(path) = path {
card_metadata.insert(0, path);
}
TranscriptCard {
id,
role: TranscriptCardRole::ViewImage,
status,
title: title.to_string(),
metadata: card_metadata,
body: response,
body_lines: Vec::new(),
children: Vec::new(),
activity_rows: Vec::new(),
subagent_card: None,
}
}