1use serde::{Deserialize, Serialize};
8
9use crate::llm::ToolCall;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "lowercase")]
13pub enum Role {
14 System,
15 User,
16 Assistant,
17 Tool,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct Message {
22 pub role: Role,
23 pub content: String,
24 #[serde(default, skip_serializing_if = "Vec::is_empty")]
25 pub tool_calls: Vec<ToolCall>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub tool_call_id: Option<String>,
28 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub reasoning_content: Option<String>,
32}
33
34impl Message {
35 pub fn system(content: impl Into<String>) -> Self {
36 Self {
37 role: Role::System,
38 content: content.into(),
39 tool_calls: Vec::new(),
40 tool_call_id: None,
41 reasoning_content: None,
42 }
43 }
44
45 pub fn user(content: impl Into<String>) -> Self {
46 Self {
47 role: Role::User,
48 content: content.into(),
49 tool_calls: Vec::new(),
50 tool_call_id: None,
51 reasoning_content: None,
52 }
53 }
54
55 pub fn assistant(content: impl Into<String>) -> Self {
56 Self {
57 role: Role::Assistant,
58 content: content.into(),
59 tool_calls: Vec::new(),
60 tool_call_id: None,
61 reasoning_content: None,
62 }
63 }
64
65 pub fn assistant_with_tool_calls(
66 content: impl Into<String>,
67 tool_calls: Vec<ToolCall>,
68 ) -> Self {
69 Self {
70 role: Role::Assistant,
71 content: content.into(),
72 tool_calls,
73 tool_call_id: None,
74 reasoning_content: None,
75 }
76 }
77
78 pub fn tool_result(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
79 Self {
80 role: Role::Tool,
81 content: content.into(),
82 tool_calls: Vec::new(),
83 tool_call_id: Some(tool_call_id.into()),
84 reasoning_content: None,
85 }
86 }
87}