agenterra_rmcp/model/
content.rs1use serde::{Deserialize, Serialize};
5use serde_json::json;
6
7use super::{AnnotateAble, Annotated, resource::ResourceContents};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "camelCase")]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
12pub struct RawTextContent {
13 pub text: String,
14}
15pub type TextContent = Annotated<RawTextContent>;
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase")]
18#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
19pub struct RawImageContent {
20 pub data: String,
22 pub mime_type: String,
23}
24
25pub type ImageContent = Annotated<RawImageContent>;
26#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
27#[serde(rename_all = "camelCase")]
28#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
29pub struct RawEmbeddedResource {
30 pub resource: ResourceContents,
31}
32pub type EmbeddedResource = Annotated<RawEmbeddedResource>;
33
34impl EmbeddedResource {
35 pub fn get_text(&self) -> String {
36 match &self.resource {
37 ResourceContents::TextResourceContents { text, .. } => text.clone(),
38 _ => String::new(),
39 }
40 }
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44#[serde(rename_all = "camelCase")]
45#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
46pub struct RawAudioContent {
47 pub data: String,
48 pub mime_type: String,
49}
50
51pub type AudioContent = Annotated<RawAudioContent>;
52
53#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
54#[serde(tag = "type", rename_all = "camelCase")]
55#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
56pub enum RawContent {
57 Text(RawTextContent),
58 Image(RawImageContent),
59 Resource(RawEmbeddedResource),
60 Audio(AudioContent),
61}
62
63pub type Content = Annotated<RawContent>;
64
65impl RawContent {
66 pub fn json<S: Serialize>(json: S) -> Result<Self, crate::Error> {
67 let json = serde_json::to_string(&json).map_err(|e| {
68 crate::Error::internal_error(
69 "fail to serialize response to json",
70 Some(json!(
71 {"reason": e.to_string()}
72 )),
73 )
74 })?;
75 Ok(RawContent::text(json))
76 }
77
78 pub fn text<S: Into<String>>(text: S) -> Self {
79 RawContent::Text(RawTextContent { text: text.into() })
80 }
81
82 pub fn image<S: Into<String>, T: Into<String>>(data: S, mime_type: T) -> Self {
83 RawContent::Image(RawImageContent {
84 data: data.into(),
85 mime_type: mime_type.into(),
86 })
87 }
88
89 pub fn resource(resource: ResourceContents) -> Self {
90 RawContent::Resource(RawEmbeddedResource { resource })
91 }
92
93 pub fn embedded_text<S: Into<String>, T: Into<String>>(uri: S, content: T) -> Self {
94 RawContent::Resource(RawEmbeddedResource {
95 resource: ResourceContents::TextResourceContents {
96 uri: uri.into(),
97 mime_type: Some("text".to_string()),
98 text: content.into(),
99 },
100 })
101 }
102
103 pub fn as_text(&self) -> Option<&RawTextContent> {
105 match self {
106 RawContent::Text(text) => Some(text),
107 _ => None,
108 }
109 }
110
111 pub fn as_image(&self) -> Option<&RawImageContent> {
113 match self {
114 RawContent::Image(image) => Some(image),
115 _ => None,
116 }
117 }
118
119 pub fn as_resource(&self) -> Option<&RawEmbeddedResource> {
121 match self {
122 RawContent::Resource(resource) => Some(resource),
123 _ => None,
124 }
125 }
126}
127
128impl Content {
129 pub fn text<S: Into<String>>(text: S) -> Self {
130 RawContent::text(text).no_annotation()
131 }
132
133 pub fn image<S: Into<String>, T: Into<String>>(data: S, mime_type: T) -> Self {
134 RawContent::image(data, mime_type).no_annotation()
135 }
136
137 pub fn resource(resource: ResourceContents) -> Self {
138 RawContent::resource(resource).no_annotation()
139 }
140
141 pub fn embedded_text<S: Into<String>, T: Into<String>>(uri: S, content: T) -> Self {
142 RawContent::embedded_text(uri, content).no_annotation()
143 }
144
145 pub fn json<S: Serialize>(json: S) -> Result<Self, crate::Error> {
146 RawContent::json(json).map(|c| c.no_annotation())
147 }
148}
149
150#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
151pub struct JsonContent<S: Serialize>(S);
152pub trait IntoContents {
154 fn into_contents(self) -> Vec<Content>;
155}
156
157impl IntoContents for Content {
158 fn into_contents(self) -> Vec<Content> {
159 vec![self]
160 }
161}
162
163impl IntoContents for String {
164 fn into_contents(self) -> Vec<Content> {
165 vec![Content::text(self)]
166 }
167}