1use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
30#[serde(tag = "type", rename_all = "snake_case")]
31#[schemars(extend("discriminator" = {"propertyName": "type"}))]
32#[non_exhaustive]
33pub enum ContentBlock {
34 Text(TextContent),
39 Image(ImageContent),
43 Audio(AudioContent),
47 ResourceLink(ResourceLink),
51 Resource(EmbeddedResource),
57}
58
59#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
61#[non_exhaustive]
62pub struct TextContent {
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub annotations: Option<Annotations>,
65 pub text: String,
66 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
68 pub meta: Option<serde_json::Value>,
69}
70
71impl TextContent {
72 pub fn new(text: impl Into<String>) -> Self {
73 Self {
74 annotations: None,
75 text: text.into(),
76 meta: None,
77 }
78 }
79
80 #[must_use]
81 pub fn annotations(mut self, annotations: Annotations) -> Self {
82 self.annotations = Some(annotations);
83 self
84 }
85
86 #[must_use]
88 pub fn meta(mut self, meta: serde_json::Value) -> Self {
89 self.meta = Some(meta);
90 self
91 }
92}
93
94impl<T: Into<String>> From<T> for ContentBlock {
95 fn from(value: T) -> Self {
96 Self::Text(TextContent::new(value))
97 }
98}
99
100#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
102#[serde(rename_all = "camelCase")]
103#[non_exhaustive]
104pub struct ImageContent {
105 #[serde(skip_serializing_if = "Option::is_none")]
106 pub annotations: Option<Annotations>,
107 pub data: String,
108 pub mime_type: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub uri: Option<String>,
111 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
113 pub meta: Option<serde_json::Value>,
114}
115
116impl ImageContent {
117 pub fn new(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
118 Self {
119 annotations: None,
120 data: data.into(),
121 mime_type: mime_type.into(),
122 uri: None,
123 meta: None,
124 }
125 }
126
127 #[must_use]
128 pub fn annotations(mut self, annotations: Annotations) -> Self {
129 self.annotations = Some(annotations);
130 self
131 }
132
133 #[must_use]
134 pub fn uri(mut self, uri: impl Into<String>) -> Self {
135 self.uri = Some(uri.into());
136 self
137 }
138
139 #[must_use]
141 pub fn meta(mut self, meta: serde_json::Value) -> Self {
142 self.meta = Some(meta);
143 self
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
149#[serde(rename_all = "camelCase")]
150#[non_exhaustive]
151pub struct AudioContent {
152 #[serde(skip_serializing_if = "Option::is_none")]
153 pub annotations: Option<Annotations>,
154 pub data: String,
155 pub mime_type: String,
156 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
158 pub meta: Option<serde_json::Value>,
159}
160
161impl AudioContent {
162 pub fn new(data: impl Into<String>, mime_type: impl Into<String>) -> Self {
163 Self {
164 annotations: None,
165 data: data.into(),
166 mime_type: mime_type.into(),
167 meta: None,
168 }
169 }
170
171 #[must_use]
172 pub fn annotations(mut self, annotations: Annotations) -> Self {
173 self.annotations = Some(annotations);
174 self
175 }
176
177 #[must_use]
179 pub fn meta(mut self, meta: serde_json::Value) -> Self {
180 self.meta = Some(meta);
181 self
182 }
183}
184
185#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
187#[non_exhaustive]
188pub struct EmbeddedResource {
189 #[serde(skip_serializing_if = "Option::is_none")]
190 pub annotations: Option<Annotations>,
191 pub resource: EmbeddedResourceResource,
192 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
194 pub meta: Option<serde_json::Value>,
195}
196
197impl EmbeddedResource {
198 #[must_use]
199 pub fn new(resource: EmbeddedResourceResource) -> Self {
200 Self {
201 annotations: None,
202 resource,
203 meta: None,
204 }
205 }
206
207 #[must_use]
208 pub fn annotations(mut self, annotations: Annotations) -> Self {
209 self.annotations = Some(annotations);
210 self
211 }
212
213 #[must_use]
215 pub fn meta(mut self, meta: serde_json::Value) -> Self {
216 self.meta = Some(meta);
217 self
218 }
219}
220
221#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
223#[serde(untagged)]
224#[non_exhaustive]
225pub enum EmbeddedResourceResource {
226 TextResourceContents(TextResourceContents),
227 BlobResourceContents(BlobResourceContents),
228}
229
230#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
232#[serde(rename_all = "camelCase")]
233#[non_exhaustive]
234pub struct TextResourceContents {
235 #[serde(skip_serializing_if = "Option::is_none")]
236 pub mime_type: Option<String>,
237 pub text: String,
238 pub uri: String,
239 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
241 pub meta: Option<serde_json::Value>,
242}
243
244impl TextResourceContents {
245 pub fn new(text: impl Into<String>, uri: impl Into<String>) -> Self {
246 Self {
247 mime_type: None,
248 text: text.into(),
249 uri: uri.into(),
250 meta: None,
251 }
252 }
253
254 #[must_use]
255 pub fn mime_type(mut self, mime_type: impl Into<String>) -> Self {
256 self.mime_type = Some(mime_type.into());
257 self
258 }
259
260 #[must_use]
262 pub fn meta(mut self, meta: serde_json::Value) -> Self {
263 self.meta = Some(meta);
264 self
265 }
266}
267
268#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
270#[serde(rename_all = "camelCase")]
271#[non_exhaustive]
272pub struct BlobResourceContents {
273 pub blob: String,
274 #[serde(skip_serializing_if = "Option::is_none")]
275 pub mime_type: Option<String>,
276 pub uri: String,
277 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
279 pub meta: Option<serde_json::Value>,
280}
281
282impl BlobResourceContents {
283 pub fn new(blob: impl Into<String>, uri: impl Into<String>) -> Self {
284 Self {
285 blob: blob.into(),
286 mime_type: None,
287 uri: uri.into(),
288 meta: None,
289 }
290 }
291
292 #[must_use]
293 pub fn mime_type(mut self, mime_type: impl Into<String>) -> Self {
294 self.mime_type = Some(mime_type.into());
295 self
296 }
297
298 #[must_use]
300 pub fn meta(mut self, meta: serde_json::Value) -> Self {
301 self.meta = Some(meta);
302 self
303 }
304}
305
306#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema)]
308#[serde(rename_all = "camelCase")]
309#[non_exhaustive]
310pub struct ResourceLink {
311 #[serde(skip_serializing_if = "Option::is_none")]
312 pub annotations: Option<Annotations>,
313 #[serde(skip_serializing_if = "Option::is_none")]
314 pub description: Option<String>,
315 #[serde(skip_serializing_if = "Option::is_none")]
316 pub mime_type: Option<String>,
317 pub name: String,
318 #[serde(skip_serializing_if = "Option::is_none")]
319 pub size: Option<i64>,
320 #[serde(skip_serializing_if = "Option::is_none")]
321 pub title: Option<String>,
322 pub uri: String,
323 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
325 pub meta: Option<serde_json::Value>,
326}
327
328impl ResourceLink {
329 pub fn new(name: impl Into<String>, uri: impl Into<String>) -> Self {
330 Self {
331 annotations: None,
332 description: None,
333 mime_type: None,
334 name: name.into(),
335 size: None,
336 title: None,
337 uri: uri.into(),
338 meta: None,
339 }
340 }
341
342 #[must_use]
343 pub fn annotations(mut self, annotations: Annotations) -> Self {
344 self.annotations = Some(annotations);
345 self
346 }
347
348 #[must_use]
349 pub fn description(mut self, description: impl Into<String>) -> Self {
350 self.description = Some(description.into());
351 self
352 }
353
354 #[must_use]
355 pub fn mime_type(mut self, mime_type: impl Into<String>) -> Self {
356 self.mime_type = Some(mime_type.into());
357 self
358 }
359
360 #[must_use]
361 pub fn size(mut self, size: i64) -> Self {
362 self.size = Some(size);
363 self
364 }
365
366 #[must_use]
367 pub fn title(mut self, title: impl Into<String>) -> Self {
368 self.title = Some(title.into());
369 self
370 }
371
372 #[must_use]
374 pub fn meta(mut self, meta: serde_json::Value) -> Self {
375 self.meta = Some(meta);
376 self
377 }
378}
379
380#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, JsonSchema, Default)]
382#[serde(rename_all = "camelCase")]
383#[non_exhaustive]
384pub struct Annotations {
385 #[serde(skip_serializing_if = "Option::is_none")]
386 pub audience: Option<Vec<Role>>,
387 #[serde(skip_serializing_if = "Option::is_none")]
388 pub last_modified: Option<String>,
389 #[serde(skip_serializing_if = "Option::is_none")]
390 pub priority: Option<f64>,
391 #[serde(skip_serializing_if = "Option::is_none", rename = "_meta")]
393 pub meta: Option<serde_json::Value>,
394}
395
396impl Annotations {
397 #[must_use]
398 pub fn new() -> Self {
399 Self::default()
400 }
401
402 #[must_use]
403 pub fn audience(mut self, audience: Vec<Role>) -> Self {
404 self.audience = Some(audience);
405 self
406 }
407
408 #[must_use]
409 pub fn last_modified(mut self, last_modified: impl Into<String>) -> Self {
410 self.last_modified = Some(last_modified.into());
411 self
412 }
413
414 #[must_use]
415 pub fn priority(mut self, priority: f64) -> Self {
416 self.priority = Some(priority);
417 self
418 }
419
420 #[must_use]
422 pub fn meta(mut self, meta: serde_json::Value) -> Self {
423 self.meta = Some(meta);
424 self
425 }
426}
427
428#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema)]
430#[serde(rename_all = "camelCase")]
431#[non_exhaustive]
432pub enum Role {
433 Assistant,
434 User,
435}