1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
5pub struct Attachment {
6 pub kind: AttachmentKind,
7 pub uri: String,
8 #[serde(skip_serializing_if = "Option::is_none")]
9 pub description: Option<String>,
10 #[serde(skip_serializing_if = "Option::is_none")]
11 pub media_type: Option<String>,
12}
13
14#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
16pub enum AttachmentKind {
17 File,
18 Image,
19 Audio,
20 Video,
21 Other,
22}
23
24#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
26pub enum Role {
27 System,
28 User,
29 Assistant,
30 Tool,
31}
32
33#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
35pub struct ToolCall {
36 #[serde(skip_serializing_if = "Option::is_none")]
37 pub id: Option<String>,
38 pub name: String,
39 pub arguments: serde_json::Value,
40}
41
42#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
44pub struct ToolResult {
45 pub name: String,
46 pub output: serde_json::Value,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub tool_call_id: Option<String>,
49}
50
51#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
53pub struct Message {
54 pub role: Role,
55 pub content: String,
56 #[serde(skip_serializing_if = "Option::is_none")]
57 pub tool_call: Option<ToolCall>,
58 #[serde(skip_serializing_if = "Option::is_none")]
59 pub tool_result: Option<ToolResult>,
60 #[serde(skip_serializing_if = "Vec::is_empty", default)]
61 pub attachments: Vec<Attachment>,
62}
63
64impl Message {
65 pub fn system(content: impl Into<String>) -> Self {
66 Self {
67 role: Role::System,
68 content: content.into(),
69 tool_call: None,
70 tool_result: None,
71 attachments: Vec::new(),
72 }
73 }
74
75 pub fn user(content: impl Into<String>) -> Self {
76 Self {
77 role: Role::User,
78 content: content.into(),
79 tool_call: None,
80 tool_result: None,
81 attachments: Vec::new(),
82 }
83 }
84
85 pub fn assistant(content: impl Into<String>) -> Self {
86 Self {
87 role: Role::Assistant,
88 content: content.into(),
89 tool_call: None,
90 tool_result: None,
91 attachments: Vec::new(),
92 }
93 }
94
95 pub fn tool(name: impl Into<String>, output: serde_json::Value) -> Self {
96 let name = name.into();
97
98 Self {
99 role: Role::Tool,
100 content: format!("Result from `{}`", name),
101 tool_call: None,
102 tool_result: Some(ToolResult {
103 name: name.clone(),
104 output,
105 tool_call_id: None,
106 }),
107 attachments: Vec::new(),
108 }
109 }
110
111 pub fn tool_with_call(
112 name: impl Into<String>,
113 output: serde_json::Value,
114 tool_call_id: Option<String>,
115 ) -> Self {
116 let name = name.into();
117
118 Self {
119 role: Role::Tool,
120 content: format!("Result from `{}`", name),
121 tool_call: None,
122 tool_result: Some(ToolResult {
123 name: name.clone(),
124 output,
125 tool_call_id,
126 }),
127 attachments: Vec::new(),
128 }
129 }
130}