use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ContentBlock {
Text {
text: String,
},
ToolCall {
id: String,
name: String,
arguments: String,
},
}
impl ContentBlock {
pub fn text(text: impl Into<String>) -> Self {
ContentBlock::Text { text: text.into() }
}
pub fn tool_call(
id: impl Into<String>,
name: impl Into<String>,
arguments: impl Into<String>,
) -> Self {
ContentBlock::ToolCall {
id: id.into(),
name: name.into(),
arguments: arguments.into(),
}
}
pub fn as_text(&self) -> Option<&str> {
match self {
ContentBlock::Text { text } => Some(text),
_ => None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LlmResponse {
pub content: Vec<ContentBlock>,
#[serde(skip_serializing_if = "Option::is_none")]
pub input_tokens: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub output_tokens: Option<u32>,
pub model: String,
}
impl LlmResponse {
pub fn text_only(&self) -> String {
self.content
.iter()
.filter_map(|b| b.as_text())
.collect::<Vec<_>>()
.join("")
}
}