use serde_json::{json, Value};
use crate::canonical::{CanonicalError, Content, DocumentSource, ImageSource};
use super::slot_err;
pub(super) fn content_block(c: &Content) -> Result<Option<Value>, CanonicalError> {
Ok(Some(match c {
Content::Text(t) => json!({"type": "text", "text": t}),
Content::Image { source } => json!({"type": "image", "source": image_source(source)}),
Content::Document { source } => {
json!({"type": "document", "source": document_source(source)})
}
Content::ToolUse {
id, name, input, ..
} => {
json!({"type": "tool_use", "id": id, "name": name, "input": input})
}
Content::ToolResult {
tool_use_id,
content,
is_error,
} => {
let mut v = json!({
"type": "tool_result",
"tool_use_id": tool_use_id,
"content": tool_result_content(content)?,
});
if *is_error {
v["is_error"] = json!(true); }
v
}
Content::Thinking {
text,
signature: Some(sig),
..
} => json!({"type": "thinking", "thinking": text, "signature": sig}),
Content::Thinking {
signature: None, ..
} => return Ok(None),
Content::RedactedThinking { data } => json!({"type": "redacted_thinking", "data": data}),
Content::ServerToolUse { id, name, input } => {
json!({"type": "server_tool_use", "id": id, "name": name, "input": input})
}
Content::ServerToolResult {
kind,
tool_use_id,
content,
} => json!({"type": kind, "tool_use_id": tool_use_id, "content": content}),
}))
}
fn image_source(s: &ImageSource) -> Value {
match s {
ImageSource::Base64 { media_type, data } => {
json!({"type": "base64", "media_type": media_type, "data": data})
}
ImageSource::Url { url } => json!({"type": "url", "url": url}),
}
}
fn document_source(s: &DocumentSource) -> Value {
match s {
DocumentSource::Base64 { media_type, data } => {
json!({"type": "base64", "media_type": media_type, "data": data})
}
DocumentSource::Url { url } => json!({"type": "url", "url": url}),
}
}
fn tool_result_content(content: &[Content]) -> Result<Value, CanonicalError> {
let mut blocks = Vec::new();
for c in content {
match c {
Content::Text(t) => blocks.push(json!({"type": "text", "text": t})),
Content::Image { source } => {
blocks.push(json!({"type": "image", "source": image_source(source)}))
}
_ => return Err(slot_err("tool_result")),
}
}
Ok(Value::Array(blocks))
}