@@ -29,11 +29,13 @@ public static ChatMessage ToChatMessage(this PromptMessage promptMessage)
2929 {
3030 Throw . IfNull ( promptMessage ) ;
3131
32+ AIContent ? content = ToAIContent ( promptMessage . Content ) ;
33+
3234 return new ( )
3335 {
3436 RawRepresentation = promptMessage ,
3537 Role = promptMessage . Role == Role . User ? ChatRole . User : ChatRole . Assistant ,
36- Contents = [ ToAIContent ( promptMessage . Content ) ]
38+ Contents = content is not null ? [ content ] : [ ] ,
3739 } ;
3840 }
3941
@@ -81,33 +83,33 @@ public static IList<PromptMessage> ToPromptMessages(this ChatMessage chatMessage
8183 return messages ;
8284 }
8385
84- /// <summary>Creates a new <see cref="AIContent"/> from the content of a <see cref="Content"/>.</summary>
85- /// <param name="content">The <see cref="Content"/> to convert.</param>
86- /// <returns>The created <see cref="AIContent"/>.</returns>
86+ /// <summary>Creates a new <see cref="AIContent"/> from the content of a <see cref="ContentBlock"/>.</summary>
87+ /// <param name="content">The <see cref="ContentBlock"/> to convert.</param>
88+ /// <returns>
89+ /// The created <see cref="AIContent"/>. If the content can't be converted (such as when it's a resource link), <see langword="null"/> is returned.
90+ /// </returns>
8791 /// <remarks>
8892 /// This method converts Model Context Protocol content types to the equivalent Microsoft.Extensions.AI
8993 /// content types, enabling seamless integration between the protocol and AI client libraries.
9094 /// </remarks>
91- public static AIContent ToAIContent ( this Content content )
95+ public static AIContent ? ToAIContent ( this ContentBlock content )
9296 {
9397 Throw . IfNull ( content ) ;
9498
95- AIContent ac ;
96- if ( content is { Type : "image" or "audio" , MimeType : not null , Data : not null } )
99+ AIContent ? ac = content switch
97100 {
98- ac = new DataContent ( Convert . FromBase64String ( content . Data ) , content . MimeType ) ;
99- }
100- else if ( content is { Type : "resource" } && content . Resource is { } resourceContents )
101- {
102- ac = resourceContents . ToAIContent ( ) ;
103- }
104- else
101+ TextContentBlock textContent => new TextContent ( textContent . Text ) ,
102+ ImageContentBlock imageContent => new DataContent ( Convert . FromBase64String ( imageContent . Data ) , imageContent . MimeType ) ,
103+ AudioContentBlock audioContent => new DataContent ( Convert . FromBase64String ( audioContent . Data ) , audioContent . MimeType ) ,
104+ EmbeddedResourceBlock resourceContent => resourceContent . Resource . ToAIContent ( ) ,
105+ _ => null ,
106+ } ;
107+
108+ if ( ac is not null )
105109 {
106- ac = new TextContent ( content . Text ) ;
110+ ac . RawRepresentation = content ;
107111 }
108112
109- ac . RawRepresentation = content ;
110-
111113 return ac ;
112114 }
113115
@@ -135,8 +137,8 @@ public static AIContent ToAIContent(this ResourceContents content)
135137 return ac ;
136138 }
137139
138- /// <summary>Creates a list of <see cref="AIContent"/> from a sequence of <see cref="Content "/>.</summary>
139- /// <param name="contents">The <see cref="Content "/> instances to convert.</param>
140+ /// <summary>Creates a list of <see cref="AIContent"/> from a sequence of <see cref="ContentBlock "/>.</summary>
141+ /// <param name="contents">The <see cref="ContentBlock "/> instances to convert.</param>
140142 /// <returns>The created <see cref="AIContent"/> instances.</returns>
141143 /// <remarks>
142144 /// <para>
@@ -145,15 +147,15 @@ public static AIContent ToAIContent(this ResourceContents content)
145147 /// when processing the contents of a message or response.
146148 /// </para>
147149 /// <para>
148- /// Each <see cref="Content "/> object is converted using <see cref="ToAIContent(Content )"/>,
150+ /// Each <see cref="ContentBlock "/> object is converted using <see cref="ToAIContent(ContentBlock )"/>,
149151 /// preserving the type-specific conversion logic for text, images, audio, and resources.
150152 /// </para>
151153 /// </remarks>
152- public static IList < AIContent > ToAIContents ( this IEnumerable < Content > contents )
154+ public static IList < AIContent > ToAIContents ( this IEnumerable < ContentBlock > contents )
153155 {
154156 Throw . IfNull ( contents ) ;
155157
156- return [ .. contents . Select ( ToAIContent ) ] ;
158+ return [ .. contents . Select ( ToAIContent ) . OfType < AIContent > ( ) ] ;
157159 }
158160
159161 /// <summary>Creates a list of <see cref="AIContent"/> from a sequence of <see cref="ResourceContents"/>.</summary>
@@ -167,7 +169,7 @@ public static IList<AIContent> ToAIContents(this IEnumerable<Content> contents)
167169 /// </para>
168170 /// <para>
169171 /// Each <see cref="ResourceContents"/> object is converted using <see cref="ToAIContent(ResourceContents)"/>,
170- /// preserving the type-specific conversion logic: text resources become <see cref="TextContent "/> objects and
172+ /// preserving the type-specific conversion logic: text resources become <see cref="TextContentBlock "/> objects and
171173 /// binary resources become <see cref="DataContent"/> objects.
172174 /// </para>
173175 /// </remarks>
@@ -178,29 +180,38 @@ public static IList<AIContent> ToAIContents(this IEnumerable<ResourceContents> c
178180 return [ .. contents . Select ( ToAIContent ) ] ;
179181 }
180182
181- internal static Content ToContent ( this AIContent content ) =>
183+ internal static ContentBlock ToContent ( this AIContent content ) =>
182184 content switch
183185 {
184- TextContent textContent => new ( )
186+ TextContent textContent => new TextContentBlock
185187 {
186188 Text = textContent . Text ,
187- Type = "text" ,
188189 } ,
189190
190- DataContent dataContent => new ( )
191+ DataContent dataContent when dataContent . HasTopLevelMediaType ( "image" ) => new ImageContentBlock ( )
191192 {
192193 Data = dataContent . Base64Data . ToString ( ) ,
193194 MimeType = dataContent . MediaType ,
194- Type =
195- dataContent . HasTopLevelMediaType ( "image" ) ? "image" :
196- dataContent . HasTopLevelMediaType ( "audio" ) ? "audio" :
197- "resource" ,
198195 } ,
199-
200- _ => new ( )
196+
197+ DataContent dataContent when dataContent . HasTopLevelMediaType ( "audio" ) => new AudioContentBlock ( )
198+ {
199+ Data = dataContent . Base64Data . ToString ( ) ,
200+ MimeType = dataContent . MediaType ,
201+ } ,
202+
203+ DataContent dataContent => new EmbeddedResourceBlock ( )
204+ {
205+ Resource = new BlobResourceContents ( )
206+ {
207+ Blob = dataContent . Base64Data . ToString ( ) ,
208+ MimeType = dataContent . MediaType ,
209+ }
210+ } ,
211+
212+ _ => new TextContentBlock
201213 {
202214 Text = JsonSerializer . Serialize ( content , McpJsonUtilities . DefaultOptions . GetTypeInfo ( typeof ( object ) ) ) ,
203- Type = "text" ,
204215 }
205216 } ;
206217}
0 commit comments