1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub struct Annotations {
6 #[serde(skip_serializing_if = "Option::is_none")]
7 pub audience: Option<Vec<Role>>,
8 #[serde(skip_serializing_if = "Option::is_none")]
10 pub priority: Option<f64>,
11}
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
14#[serde(rename_all = "lowercase")]
15pub enum Role {
16 User,
17 Assistant,
18}
19
20#[derive(Debug, Clone, Serialize, Deserialize)]
22pub struct TextContent {
23 pub text: String,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub annotations: Option<Annotations>,
26}
27
28impl TextContent {
29 pub fn new(text: impl Into<String>) -> Self {
30 Self {
31 text: text.into(),
32 annotations: None,
33 }
34 }
35}
36
37#[derive(Debug, Clone, Serialize, Deserialize)]
39#[serde(rename_all = "camelCase")]
40pub struct ImageContent {
41 pub data: String,
43 pub mime_type: String,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub annotations: Option<Annotations>,
46}
47
48impl ImageContent {
49 pub fn new(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
50 Self {
51 data: data.into(),
52 mime_type: mime_type.into(),
53 annotations: None,
54 }
55 }
56
57 pub fn png(data: impl Into<String>) -> Self {
58 Self::new(data, "image/png")
59 }
60
61 pub fn jpeg(data: impl Into<String>) -> Self {
62 Self::new(data, "image/jpeg")
63 }
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct AudioContent {
70 pub data: String,
71 pub mime_type: String,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub annotations: Option<Annotations>,
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize)]
78pub struct EmbeddedResource {
79 pub resource: ResourceContents,
80 #[serde(skip_serializing_if = "Option::is_none")]
81 pub annotations: Option<Annotations>,
82}
83
84#[derive(Debug, Clone, Serialize, Deserialize)]
86#[serde(untagged)]
87pub enum ResourceContents {
88 Text(TextResourceContents),
89 Blob(BlobResourceContents),
90}
91
92impl ResourceContents {
93 pub fn text(uri: impl Into<String>, text: impl Into<String>) -> Self {
94 Self::Text(TextResourceContents {
95 uri: uri.into(),
96 mime_type: Some("text/plain".to_owned()),
97 text: text.into(),
98 })
99 }
100
101 pub fn blob(
102 uri: impl Into<String>,
103 blob: impl Into<String>,
104 mime_type: impl Into<String>,
105 ) -> Self {
106 Self::Blob(BlobResourceContents {
107 uri: uri.into(),
108 mime_type: Some(mime_type.into()),
109 blob: blob.into(),
110 })
111 }
112}
113
114#[derive(Debug, Clone, Serialize, Deserialize)]
115#[serde(rename_all = "camelCase")]
116pub struct TextResourceContents {
117 pub uri: String,
118 #[serde(skip_serializing_if = "Option::is_none")]
119 pub mime_type: Option<String>,
120 pub text: String,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
124#[serde(rename_all = "camelCase")]
125pub struct BlobResourceContents {
126 pub uri: String,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub mime_type: Option<String>,
129 pub blob: String,
131}
132
133#[derive(Debug, Clone, Serialize, Deserialize)]
135#[serde(tag = "type", rename_all = "lowercase")]
136pub enum Content {
137 Text(TextContent),
138 Image(ImageContent),
139 Audio(AudioContent),
140 Resource(EmbeddedResource),
141}
142
143impl Content {
144 pub fn text(text: impl Into<String>) -> Self {
145 Self::Text(TextContent::new(text))
146 }
147
148 pub fn image(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
149 Self::Image(ImageContent::new(data, mime_type))
150 }
151
152 pub fn resource(resource: ResourceContents) -> Self {
153 Self::Resource(EmbeddedResource {
154 resource,
155 annotations: None,
156 })
157 }
158}
159
160impl From<TextContent> for Content {
161 fn from(t: TextContent) -> Self {
162 Self::Text(t)
163 }
164}
165
166impl From<ImageContent> for Content {
167 fn from(i: ImageContent) -> Self {
168 Self::Image(i)
169 }
170}