use serde::{Deserialize, Serialize};
use crate::tool::{ToolCall, ToolResult};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Role {
System,
User,
Assistant,
Tool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Content {
Text(String),
ToolCall(ToolCall),
ToolResult(ToolResult),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Message {
pub role: Role,
pub content: Vec<Content>,
}
impl Message {
pub fn text(role: Role, text: impl Into<String>) -> Self {
Self {
role,
content: vec![Content::Text(text.into())],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::tool::ToolCall;
#[test]
fn message_round_trips_through_serde() {
let message = Message {
role: Role::Assistant,
content: vec![
Content::Text("running the check".into()),
Content::ToolCall(ToolCall {
id: "call_1".into(),
name: "cargo_test".into(),
args: serde_json::json!({ "package": "rhema-core" }),
provider_data: serde_json::Value::Null,
}),
],
};
let json = serde_json::to_string(&message).unwrap();
let back: Message = serde_json::from_str(&json).unwrap();
assert_eq!(back, message);
}
}