use serde::{Deserialize, Serialize};
use crate::{ContentPart, ToolUseBlock, Usage, text_content, text_of};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "role", rename_all = "snake_case")]
pub enum Message {
User(UserMessage),
Assistant(AssistantMessage),
System(SystemMessage),
#[serde(rename = "tool_result", alias = "tool")]
Tool(ToolResultMessage),
}
impl Message {
#[must_use]
pub fn role(&self) -> &'static str {
match self {
Self::User(_) => "user",
Self::Assistant(_) => "assistant",
Self::System(_) => "system",
Self::Tool(_) => "tool_result",
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct UserMessage {
pub content: Vec<ContentPart>,
}
impl UserMessage {
#[must_use]
pub fn from_text(text: impl Into<String>) -> Self {
Self {
content: text_content(text),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
pub struct AssistantMessage {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub content: Vec<ContentPart>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub tool_calls: Vec<ToolUseBlock>,
#[serde(skip_serializing_if = "Option::is_none")]
pub usage: Option<Usage>,
}
impl AssistantMessage {
#[must_use]
pub fn text(&self) -> String {
text_of(&self.content)
}
#[must_use]
pub fn has_tool_calls(&self) -> bool {
!self.tool_calls.is_empty()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SystemMessage {
pub content: String,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ToolResultMessage {
#[serde(alias = "tool_use_id")]
pub id: String,
pub content: String,
#[serde(default)]
pub is_error: bool,
}
#[must_use]
pub fn user(text: &str) -> Message {
Message::User(UserMessage::from_text(text))
}
#[must_use]
pub fn assistant(text: &str) -> Message {
Message::Assistant(AssistantMessage {
content: text_content(text),
tool_calls: Vec::new(),
usage: None,
})
}
#[must_use]
pub fn system(text: &str) -> Message {
Message::System(SystemMessage {
content: text.to_string(),
})
}
#[must_use]
pub fn tool_result_msg(tool_use_id: &str, content: &str, is_error: bool) -> Message {
Message::Tool(ToolResultMessage {
id: tool_use_id.to_string(),
content: content.to_string(),
is_error,
})
}