@@ -25,11 +25,12 @@ async Task<ChatResponse> IChatClient.GetResponseAsync(
2525 {
2626 CreateMessageParams request = CreateRequest ( messages , options ) ;
2727
28- var response = await this . Messages . MessagesPostAsync ( request , anthropicVersion : "2023-06-01" , cancellationToken ) . ConfigureAwait ( false ) ;
28+ var response = await this . Messages . MessagesPostAsync ( request , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
2929
3030 ChatMessage responseMessage = new ( )
3131 {
32- Role = response . Role == MessageRole . Assistant ? ChatRole . Assistant : ChatRole . User ,
32+ MessageId = response . Id ,
33+ Role = ChatRole . Assistant ,
3334 RawRepresentation = response ,
3435 } ;
3536
@@ -38,47 +39,37 @@ async Task<ChatResponse> IChatClient.GetResponseAsync(
3839 ( responseMessage . AdditionalProperties ??= [ ] ) [ nameof ( response . StopSequence ) ] = response . StopSequence ;
3940 }
4041
41- // if (response.Content.Value1 is string stringContents)
42- // {
43- // responseMessage.Contents.Add(new TextContent(stringContents));
44- // }
45- //else if (response.Content.Value2 is IList<Block> blocks)
42+ foreach ( var block in response . Content )
4643 {
47- foreach ( var block in response . Content )
44+ if ( block . IsText )
4845 {
49- if ( block . IsText )
46+ responseMessage . Contents . Add ( new TextContent ( block . Text ! . Text ) { RawRepresentation = block } ) ;
47+ }
48+ else if ( block . IsThinking )
49+ {
50+ responseMessage . Contents . Add ( new TextReasoningContent ( block . Thinking ! . Thinking )
5051 {
51- responseMessage . Contents . Add ( new TextContent ( block . Text ! . Text ) { RawRepresentation = block . Text } ) ;
52- }
53- // else if (block.IsImage)
54- // {
55- // responseMessage.Contents.Add(new ImageContent(
56- // block.Image!.Source.Data,
57- // block.Image!.Source.MediaType switch
58- // {
59- // ImageBlockSourceMediaType.ImagePng => "image/png",
60- // ImageBlockSourceMediaType.ImageGif => "image/gif",
61- // ImageBlockSourceMediaType.ImageWebp => "image/webp",
62- // _ => "image/jpeg",
63- // })
64- // {
65- // RawRepresentation = block.Image
66- // });
67- // }
68- else if ( block . IsToolUse )
52+ AdditionalProperties = new ( ) { [ nameof ( RequestThinkingBlock . Signature ) ] = block . Thinking . Signature } ,
53+ RawRepresentation = block ,
54+ } ) ;
55+ }
56+ else if ( block . IsToolUse )
57+ {
58+ responseMessage . Contents . Add ( new FunctionCallContent (
59+ block . ToolUse ! . Id ,
60+ block . ToolUse ! . Name ,
61+ block . ToolUse ! . Input is JsonElement e ? ( IDictionary < string , object ? > ? ) e . Deserialize (
62+ JsonSerializerContext . Options . GetTypeInfo ( typeof ( Dictionary < string , object ? > ) ) ) :
63+ null )
6964 {
70- responseMessage . Contents . Add ( new FunctionCallContent (
71- block . ToolUse ! . Id ,
72- block . ToolUse ! . Name ,
73- block . ToolUse ! . Input is JsonElement e ? ( IDictionary < string , object ? > ? ) e . Deserialize (
74- JsonSerializerContext . Options . GetTypeInfo ( typeof ( Dictionary < string , object ? > ) ) ) :
75- null ) ) ;
76- }
65+ RawRepresentation = block
66+ } ) ;
7767 }
7868 }
7969
8070 ChatResponse completion = new ( responseMessage )
8171 {
72+ RawRepresentation = response ,
8273 ResponseId = response . Id ,
8374 ModelId = response . Model ,
8475 FinishReason = response . StopReason switch
@@ -99,15 +90,15 @@ async Task<ChatResponse> IChatClient.GetResponseAsync(
9990 TotalTokenCount = u . InputTokens + u . OutputTokens ,
10091 } ;
10192
102- // if (u.CacheCreationInputTokens is not null )
103- // {
104- // (completion.Usage.AdditionalProperties ??= [])[nameof(u.CacheCreationInputTokens)] = u.CacheCreationInputTokens ;
105- // }
106- //
107- // if (u.CacheReadInputTokens is not null )
108- // {
109- // (completion.Usage.AdditionalProperties ??= [])[nameof(u.CacheReadInputTokens)] = u.CacheReadInputTokens ;
110- // }
93+ if ( u . CacheCreationInputTokens is int cacheCreationTokens )
94+ {
95+ ( completion . Usage . AdditionalCounts ??= [ ] ) [ nameof ( u . CacheCreationInputTokens ) ] = cacheCreationTokens ;
96+ }
97+
98+ if ( u . CacheReadInputTokens is int cacheReadTokens )
99+ {
100+ ( completion . Usage . AdditionalCounts ??= [ ] ) [ nameof ( u . CacheReadInputTokens ) ] = cacheReadTokens ;
101+ }
111102 }
112103
113104 return completion ;
@@ -119,39 +110,26 @@ async IAsyncEnumerable<ChatResponseUpdate> IChatClient.GetStreamingResponseAsync
119110 CreateMessageParams request = CreateRequest ( messages , options ) ;
120111
121112 IAsyncEnumerable < MessageStreamEvent > enumerable =
122- CreateMessageAsStreamAsync ( request , anthropicVersion : "2023-06-01" , cancellationToken ) ;
113+ CreateMessageAsStreamAsync ( request , cancellationToken : cancellationToken ) ;
123114
124115 await foreach ( var response in enumerable . ConfigureAwait ( false ) )
125116 {
126- var chatResponseUpdate = new ChatResponseUpdate ( ) ;
117+ ChatResponseUpdate chatResponseUpdate = new ( ) ;
118+
127119 if ( response . IsContentBlockDelta )
128120 {
129121 var delta = response . ContentBlockDelta ! . Delta ;
130122 if ( delta . IsTextDelta )
131123 {
132- chatResponseUpdate . Contents . Add ( new TextContent ( delta . TextDelta ! . Text ) { RawRepresentation = delta . TextDelta ! . Text } ) ;
124+ chatResponseUpdate . Contents . Add ( new TextContent ( delta . TextDelta ! . Text ) { RawRepresentation = response } ) ;
133125 }
134126 }
135127
136128 yield return chatResponseUpdate ;
137- // yield return new ChatResponseUpdate
138- // {
139- // //AdditionalProperties = response.AdditionalProperties,
140- // //AuthorName = choice.AuthorName,
141- // ChatThreadId = response.ChatThreadId,
142- // ChoiceIndex = i,
143- // ResponseId = response.ResponseId,
144- // Contents = choice.Contents,
145- // CreatedAt = response.CreatedAt,
146- // FinishReason = response.FinishReason,
147- // ModelId = response.ModelId,
148- // RawRepresentation = choice.RawRepresentation,
149- // Role = choice.Role,
150- // };
151129 }
152130 }
153131
154- private static CreateMessageParams CreateRequest ( IEnumerable < ChatMessage > chatMessages , ChatOptions ? options )
132+ private CreateMessageParams CreateRequest ( IEnumerable < ChatMessage > chatMessages , ChatOptions ? options )
155133 {
156134 string ? systemMessage = null ;
157135
@@ -177,21 +155,60 @@ private static CreateMessageParams CreateRequest(IEnumerable<ChatMessage> chatMe
177155 blocks . Add ( new InputContentBlock ( new RequestTextBlock { Text = tc . Text } ) ) ;
178156 break ;
179157
180- case DataContent ic when ic . HasTopLevelMediaType ( "image" ) :
158+ case TextReasoningContent trc :
159+ blocks . Add ( new InputContentBlock ( new RequestThinkingBlock
160+ {
161+ Thinking = trc . Text ,
162+ Signature = trc . AdditionalProperties ? . TryGetValue ( nameof ( RequestThinkingBlock . Signature ) , out string ? sig ) is true ? sig : "" ,
163+ } ) ) ;
164+ break ;
165+
166+ case DataContent dc when dc . HasTopLevelMediaType ( "image" ) :
181167 blocks . Add ( new InputContentBlock ( new RequestImageBlock
182168 {
183169 Source = new Base64ImageSource
184170 {
185- MediaType = ic . MediaType switch
171+ MediaType = dc . MediaType switch
186172 {
187173 "image/png" => Base64ImageSourceMediaType . ImagePng ,
188174 "image/gif" => Base64ImageSourceMediaType . ImageGif ,
189175 "image/webp" => Base64ImageSourceMediaType . ImageWebp ,
190176 _ => Base64ImageSourceMediaType . ImageJpeg ,
191177 } ,
192- Data = ic . Data . ToArray ( ) ?? [ ] , //Convert.ToBase64String(ic.Data?.ToArray() ?? []) ,
178+ Data = dc . Data . ToArray ( ) ?? [ ] ,
193179 Type = Base64ImageSourceType . Base64 ,
194- }
180+ } ,
181+ } ) ) ;
182+ break ;
183+
184+ case DataContent dc when dc . MediaType . Equals ( "application/pdf" , StringComparison . OrdinalIgnoreCase ) :
185+ blocks . Add ( new InputContentBlock ( new RequestDocumentBlock
186+ {
187+ Source = new Base64PDFSource
188+ {
189+ MediaType = Base64PDFSourceMediaType . ApplicationPdf ,
190+ Data = dc . Data . ToArray ( ) ?? [ ] ,
191+ } ,
192+ } ) ) ;
193+ break ;
194+
195+ case UriContent uc when uc . HasTopLevelMediaType ( "image" ) :
196+ blocks . Add ( new InputContentBlock ( new RequestImageBlock
197+ {
198+ Source = new URLImageSource
199+ {
200+ Url = uc . Uri . ToString ( ) ,
201+ } ,
202+ } ) ) ;
203+ break ;
204+
205+ case UriContent uc when uc . MediaType . Equals ( "application/pdf" , StringComparison . OrdinalIgnoreCase ) :
206+ blocks . Add ( new InputContentBlock ( new RequestDocumentBlock
207+ {
208+ Source = new URLPDFSource
209+ {
210+ Url = uc . Uri . ToString ( ) ,
211+ } ,
195212 } ) ) ;
196213 break ;
197214
@@ -225,36 +242,78 @@ private static CreateMessageParams CreateRequest(IEnumerable<ChatMessage> chatMe
225242 }
226243 }
227244
228- var request = new CreateMessageParams
245+ CreateMessageParams ? request = options ? . RawRepresentationFactory ? . Invoke ( this ) as CreateMessageParams ;
246+ if ( request is not null )
229247 {
230- MaxTokens = options ? . MaxOutputTokens ?? 250 ,
231- Messages = messages ,
232- Model = options ? . ModelId ?? string . Empty ,
233- StopSequences = options ? . StopSequences ,
234- System = systemMessage is not null ? new ( systemMessage ) : null ,
235- Temperature = options ? . Temperature ,
236- TopP = options ? . TopP ,
237- TopK = options ? . TopK ,
238- ToolChoice =
239- options ? . Tools is not { Count : > 0 } ? null :
240- options ? . ToolMode is AutoChatToolMode ? new ToolChoice ( new ToolChoiceAuto ( ) ) :
241- options ? . ToolMode is RequiredChatToolMode r
242- ? r . RequiredFunctionName is not null
243- ? new ToolChoice ( new ToolChoiceTool
244- {
245- Name = r . RequiredFunctionName ,
246- } )
247- : new ToolChoice ( new ToolChoiceAny ( ) )
248- : ( ToolChoice ? ) null ,
249- Tools = options ? . Tools is IList < AITool > tools ?
250- tools . OfType < AIFunction > ( ) . Select ( f => new global ::Anthropic . OneOf < global ::Anthropic . Tool , global ::Anthropic . BashTool20250124 , global ::Anthropic . TextEditor20250124 , global ::Anthropic . WebSearchTool20250305 > ( new Tool
248+ request . Model = options ? . ModelId ?? string . Empty ;
249+ if ( request . Messages is null )
250+ {
251+ request . Messages = messages ;
252+ }
253+ else
254+ {
255+ foreach ( var message in messages )
251256 {
252- Name = f . Name ,
253- Description = f . Description ,
254- InputSchema = CreateSchema ( f ) ,
255- } ) ) . ToList ( ) :
256- null ,
257- } ;
257+ request . Messages . Add ( message ) ;
258+ }
259+ }
260+ }
261+ else
262+ {
263+ request = new ( )
264+ {
265+ Model = options ? . ModelId ?? string . Empty ,
266+ MaxTokens = options ? . MaxOutputTokens ?? 250 ,
267+ Messages = messages ,
268+ } ;
269+ }
270+
271+ request . StopSequences ??= options ? . StopSequences ;
272+ if ( systemMessage is not null )
273+ {
274+ request . System ??= new ( systemMessage ) ;
275+ }
276+ request . Temperature ??= options ? . Temperature ;
277+ request . TopP ??= options ? . TopP ;
278+ request . TopK ??= options ? . TopK ;
279+
280+ request . ToolChoice ??=
281+ options ? . Tools is not { Count : > 0 } ? null :
282+ options ? . ToolMode is AutoChatToolMode ? new ToolChoice ( new ToolChoiceAuto ( ) ) :
283+ options ? . ToolMode is RequiredChatToolMode r
284+ ? r . RequiredFunctionName is not null
285+ ? new ToolChoice ( new ToolChoiceTool
286+ {
287+ Name = r . RequiredFunctionName ,
288+ } )
289+ : new ToolChoice ( new ToolChoiceAny ( ) )
290+ : ( ToolChoice ? ) null ;
291+
292+ if ( options ? . Tools is { Count : > 0 } aitools )
293+ {
294+ var tools = request . Tools ?? [ ] ;
295+ request . Tools = tools ;
296+
297+ foreach ( var tool in aitools )
298+ {
299+ switch ( tool )
300+ {
301+ case AIFunction f :
302+ tools . Add ( new Tool
303+ {
304+ Name = f . Name ,
305+ Description = f . Description ,
306+ InputSchema = CreateSchema ( f ) ,
307+ } ) ;
308+ break ;
309+
310+ case HostedWebSearchTool ws :
311+ tools . Add ( new WebSearchTool20250305 ( ) ) ;
312+ break ;
313+ }
314+ }
315+ }
316+
258317 return request ;
259318 }
260319
0 commit comments