use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContentBlock {
Text(TextBlock),
Thinking(ThinkingBlock),
ToolUse(ToolUseBlock),
ToolResult(ToolResultBlock),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct TextBlock {
pub text: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ThinkingBlock {
pub thinking: String,
pub signature: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolUseBlock {
pub id: String,
pub name: String,
pub input: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolResultBlock {
pub tool_use_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub content: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_error: Option<bool>,
}
impl ContentBlock {
pub fn is_text(&self) -> bool {
matches!(self, ContentBlock::Text(_))
}
pub fn is_thinking(&self) -> bool {
matches!(self, ContentBlock::Thinking(_))
}
pub fn is_tool_use(&self) -> bool {
matches!(self, ContentBlock::ToolUse(_))
}
pub fn is_tool_result(&self) -> bool {
matches!(self, ContentBlock::ToolResult(_))
}
pub fn as_text(&self) -> Option<&TextBlock> {
if let ContentBlock::Text(t) = self {
Some(t)
} else {
None
}
}
pub fn as_tool_use(&self) -> Option<&ToolUseBlock> {
if let ContentBlock::ToolUse(t) = self {
Some(t)
} else {
None
}
}
}