@@ -15,6 +15,7 @@ import {
1515 type AnthropicMessagesPayload ,
1616 type AnthropicResponse ,
1717 type AnthropicTextBlock ,
18+ type AnthropicThinkingBlock ,
1819 type AnthropicTool ,
1920 type AnthropicToolResultBlock ,
2021 type AnthropicToolUseBlock ,
@@ -131,11 +132,21 @@ function handleAssistantMessage(
131132 ( block ) : block is AnthropicTextBlock => block . type === "text" ,
132133 )
133134
135+ const thinkingBlocks = message . content . filter (
136+ ( block ) : block is AnthropicThinkingBlock => block . type === "thinking" ,
137+ )
138+
139+ // Combine text and thinking blocks, as OpenAI doesn't have separate thinking blocks
140+ const allTextContent = [
141+ ...textBlocks . map ( ( b ) => b . text ) ,
142+ ...thinkingBlocks . map ( ( b ) => b . thinking ) ,
143+ ] . join ( "\n\n" )
144+
134145 return toolUseBlocks . length > 0 ?
135146 [
136147 {
137148 role : "assistant" ,
138- content : textBlocks . map ( ( b ) => b . text ) . join ( "\n\n" ) || null ,
149+ content : allTextContent || null ,
139150 tool_calls : toolUseBlocks . map ( ( toolUse ) => ( {
140151 id : toolUse . id ,
141152 type : "function" ,
@@ -169,22 +180,38 @@ function mapContent(
169180 const hasImage = content . some ( ( block ) => block . type === "image" )
170181 if ( ! hasImage ) {
171182 return content
172- . filter ( ( block ) : block is AnthropicTextBlock => block . type === "text" )
173- . map ( ( block ) => block . text )
183+ . filter (
184+ ( block ) : block is AnthropicTextBlock | AnthropicThinkingBlock =>
185+ block . type === "text" || block . type === "thinking" ,
186+ )
187+ . map ( ( block ) => ( block . type === "text" ? block . text : block . thinking ) )
174188 . join ( "\n\n" )
175189 }
176190
177191 const contentParts : Array < ContentPart > = [ ]
178192 for ( const block of content ) {
179- if ( block . type === "text" ) {
180- contentParts . push ( { type : "text" , text : block . text } )
181- } else if ( block . type === "image" ) {
182- contentParts . push ( {
183- type : "image_url" ,
184- image_url : {
185- url : `data:${ block . source . media_type } ;base64,${ block . source . data } ` ,
186- } ,
187- } )
193+ switch ( block . type ) {
194+ case "text" : {
195+ contentParts . push ( { type : "text" , text : block . text } )
196+
197+ break
198+ }
199+ case "thinking" : {
200+ contentParts . push ( { type : "text" , text : block . thinking } )
201+
202+ break
203+ }
204+ case "image" : {
205+ contentParts . push ( {
206+ type : "image_url" ,
207+ image_url : {
208+ url : `data:${ block . source . media_type } ;base64,${ block . source . data } ` ,
209+ } ,
210+ } )
211+
212+ break
213+ }
214+ // No default
188215 }
189216 }
190217 return contentParts
@@ -246,6 +273,7 @@ export function translateToAnthropic(
246273 const choice = response . choices [ 0 ]
247274 const textBlocks = getAnthropicTextBlocks ( choice . message . content )
248275 const toolUseBlocks = getAnthropicToolUseBlocks ( choice . message . tool_calls )
276+ // Note: GitHub Copilot doesn't generate thinking blocks, so we don't include them in responses
249277
250278 return {
251279 id : response . id ,
0 commit comments