use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatMessage {
pub role: String, #[serde(default)]
pub content: String,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub tool_calls: Option<Vec<ToolCall>>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub tool_call_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none", default)]
pub reasoning_content: Option<String>,
}
impl ChatMessage {
pub fn system(content: impl Into<String>) -> Self {
Self::simple("system", content)
}
pub fn user(content: impl Into<String>) -> Self {
Self::simple("user", content)
}
pub fn assistant(content: impl Into<String>) -> Self {
Self::simple("assistant", content)
}
pub fn simple(role: &str, content: impl Into<String>) -> Self {
ChatMessage {
role: role.to_string(),
content: content.into(),
tool_calls: None,
tool_call_id: None,
reasoning_content: None,
}
}
pub fn tool_result(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
ChatMessage {
role: "tool".to_string(),
content: content.into(),
tool_calls: None,
tool_call_id: Some(tool_call_id.into()),
reasoning_content: None,
}
}
pub fn assistant_with_tools(content: impl Into<String>, tool_calls: Vec<ToolCall>) -> Self {
ChatMessage {
role: "assistant".to_string(),
content: content.into(),
tool_calls: Some(tool_calls),
tool_call_id: None,
reasoning_content: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ToolCall {
pub id: String,
pub name: String,
pub arguments: String,
}
impl ToolCall {
pub fn parsed_args(&self) -> Value {
serde_json::from_str(&self.arguments).unwrap_or_else(|_| serde_json::json!({}))
}
}
#[derive(Debug, Clone, Default)]
pub struct LlmResponse {
pub text: String,
pub tool_calls: Vec<ToolCall>,
pub reasoning_content: Option<String>,
pub finish_reason: Option<String>,
}
impl LlmResponse {
pub fn is_truncated(&self) -> bool {
matches!(
self.finish_reason.as_deref(),
Some("length") | Some("max_tokens") | Some("connection_closed")
)
}
}