use rpi_ai::types::{AssistantMessage, Content, Message, ToolResultMessage, UserMessage};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum AgentMessage {
User(UserMessage),
Assistant(Box<AssistantMessage>),
ToolResult(Box<ToolResultMessage>),
Custom(CustomMessage),
}
impl AgentMessage {
pub fn role(&self) -> AgentMessageRole {
match self {
AgentMessage::User(_) => AgentMessageRole::User,
AgentMessage::Assistant(_) => AgentMessageRole::Assistant,
AgentMessage::ToolResult(_) => AgentMessageRole::ToolResult,
AgentMessage::Custom(c) => AgentMessageRole::Custom(c.role.clone()),
}
}
pub fn is_assistant(&self) -> bool {
matches!(self, AgentMessage::Assistant(_))
}
pub fn as_assistant(&self) -> Option<&AssistantMessage> {
match self {
AgentMessage::Assistant(a) => Some(a),
_ => None,
}
}
pub fn into_assistant(self) -> Option<AssistantMessage> {
match self {
AgentMessage::Assistant(a) => Some(*a),
_ => None,
}
}
}
impl From<UserMessage> for AgentMessage {
fn from(m: UserMessage) -> Self {
AgentMessage::User(m)
}
}
impl From<AssistantMessage> for AgentMessage {
fn from(m: AssistantMessage) -> Self {
AgentMessage::Assistant(Box::new(m))
}
}
impl From<ToolResultMessage> for AgentMessage {
fn from(m: ToolResultMessage) -> Self {
AgentMessage::ToolResult(Box::new(m))
}
}
impl From<Message> for AgentMessage {
fn from(m: Message) -> Self {
match m {
Message::User(u) => AgentMessage::User(u),
Message::Assistant(a) => AgentMessage::Assistant(a),
Message::ToolResult(t) => AgentMessage::ToolResult(t),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AgentMessageRole {
User,
Assistant,
ToolResult,
Custom(String),
}
impl AgentMessageRole {
pub fn as_str(&self) -> &str {
match self {
AgentMessageRole::User => "user",
AgentMessageRole::Assistant => "assistant",
AgentMessageRole::ToolResult => "toolResult",
AgentMessageRole::Custom(s) => s.as_str(),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CustomMessage {
pub role: String,
pub content: Vec<Content>,
pub data: serde_json::Value,
pub timestamp: i64,
}
impl CustomMessage {
pub fn new(role: impl Into<String>, content: Vec<Content>, data: serde_json::Value, timestamp: i64) -> Self {
Self {
role: role.into(),
content,
data,
timestamp,
}
}
}