agent_base/types/
message.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
4pub enum MessageRole {
5 System,
6 User,
7 Assistant,
8 Tool,
9}
10
11impl MessageRole {
12 pub fn as_str(&self) -> &'static str {
13 match self {
14 MessageRole::System => "system",
15 MessageRole::User => "user",
16 MessageRole::Assistant => "assistant",
17 MessageRole::Tool => "tool",
18 }
19 }
20
21 pub fn as_api_role(&self) -> &'static str {
22 self.as_str()
23 }
24}
25
26#[derive(Clone, Debug, Serialize, Deserialize)]
27pub struct Message {
28 pub role: MessageRole,
29 pub content: String,
30}
31
32#[derive(Clone, Debug, Serialize, Deserialize)]
33pub enum ChatMessage {
34 System {
35 content: String,
36 },
37 User {
38 content: String,
39 #[serde(default, skip_serializing_if = "Vec::is_empty")]
40 images: Vec<ImageAttachment>,
41 },
42 Assistant {
43 content: Option<String>,
44 reasoning_content: Option<String>,
45 tool_calls: Option<Vec<ToolCallMessage>>,
46 },
47 Tool {
48 tool_call_id: String,
49 content: String,
50 },
51}
52
53#[derive(Clone, Debug, Serialize, Deserialize)]
54pub struct ToolCallMessage {
55 pub id: String,
56 pub name: String,
57 pub arguments: String,
58}
59
60#[derive(Clone, Debug, Serialize, Deserialize)]
61pub enum ImageAttachment {
62 Url {
63 url: String,
64 #[serde(default, skip_serializing_if = "Option::is_none")]
65 detail: Option<ImageDetail>,
66 },
67 Base64 {
68 data: String,
69 #[serde(default, skip_serializing_if = "Option::is_none")]
70 media_type: Option<String>,
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 detail: Option<ImageDetail>,
73 },
74}
75
76#[derive(Clone, Debug, Serialize, Deserialize)]
77pub enum ImageDetail {
78 Low,
79 High,
80 Auto,
81}
82
83impl ChatMessage {
84 pub fn system(content: impl Into<String>) -> Self {
85 Self::System {
86 content: content.into(),
87 }
88 }
89
90 pub fn user(content: impl Into<String>) -> Self {
91 Self::User {
92 content: content.into(),
93 images: Vec::new(),
94 }
95 }
96
97 pub fn user_with_images(content: impl Into<String>, images: Vec<ImageAttachment>) -> Self {
98 Self::User {
99 content: content.into(),
100 images,
101 }
102 }
103
104 pub fn assistant(content: impl Into<String>) -> Self {
105 Self::Assistant {
106 content: Some(content.into()),
107 reasoning_content: None,
108 tool_calls: None,
109 }
110 }
111
112 pub fn assistant_with_reasoning(
113 content: impl Into<String>,
114 reasoning: impl Into<String>,
115 ) -> Self {
116 Self::Assistant {
117 content: Some(content.into()),
118 reasoning_content: Some(reasoning.into()),
119 tool_calls: None,
120 }
121 }
122
123 pub fn assistant_tool_call(tool_call_id: impl Into<String>, tool_name: impl Into<String>, arguments: impl Into<String>) -> Self {
124 Self::Assistant {
125 content: None,
126 reasoning_content: None,
127 tool_calls: Some(vec![ToolCallMessage {
128 id: tool_call_id.into(),
129 name: tool_name.into(),
130 arguments: arguments.into(),
131 }]),
132 }
133 }
134
135 pub fn tool(tool_call_id: impl Into<String>, content: impl Into<String>) -> Self {
136 Self::Tool {
137 tool_call_id: tool_call_id.into(),
138 content: content.into(),
139 }
140 }
141}