@@ -120,13 +120,15 @@ func (o *openAIToAWSBedrockTranslatorV1ChatCompletion) openAIToolsToBedrockToolC
120120 for i := range openAIReq .Tools {
121121 toolDefinition := & openAIReq .Tools [i ]
122122 if toolDefinition .Function != nil {
123- var toolName , toolDes string
124- toolName = toolDefinition .Function .Name
125- toolDes = toolDefinition .Function .Description
123+ toolName := toolDefinition .Function .Name
124+ var toolDesc * string
125+ if toolDefinition .Function .Description != "" {
126+ toolDesc = & toolDefinition .Function .Description
127+ }
126128 tool := & awsbedrock.Tool {
127129 ToolSpec : & awsbedrock.ToolSpecification {
128130 Name : & toolName ,
129- Description : & toolDes ,
131+ Description : toolDesc ,
130132 InputSchema : & awsbedrock.ToolInputSchema {
131133 JSON : toolDefinition .Function .Parameters ,
132134 },
@@ -247,21 +249,58 @@ func unmarshalToolCallArguments(arguments string) (map[string]any, error) {
247249func (o * openAIToAWSBedrockTranslatorV1ChatCompletion ) openAIMessageToBedrockMessageRoleAssistant (
248250 openAiMessage * openai.ChatCompletionAssistantMessageParam , role string ,
249251) (* awsbedrock.Message , error ) {
250- var bedrockMessage * awsbedrock.Message
252+ bedrockMessage := & awsbedrock.Message { Role : role }
251253 contentBlocks := make ([]* awsbedrock.ContentBlock , 0 )
254+
255+ var contentParts []openai.ChatCompletionAssistantMessageParamContent
252256 if v , ok := openAiMessage .Content .Value .(string ); ok && len (v ) > 0 {
253- contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {Text : & v })
254- } else if content , ok := openAiMessage .Content .Value .(openai.ChatCompletionAssistantMessageParamContent ); ok {
255- if content .Type == openai .ChatCompletionAssistantMessageParamContentTypeRefusal {
256- contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {Text : content .Refusal })
257- } else if content .Text != nil {
258- contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {Text : content .Text })
257+ // Case 1: Content is a simple string.
258+ contentParts = append (contentParts , openai.ChatCompletionAssistantMessageParamContent {Type : openai .ChatCompletionAssistantMessageParamContentTypeText , Text : & v })
259+ } else if singleContent , ok := openAiMessage .Content .Value .(openai.ChatCompletionAssistantMessageParamContent ); ok {
260+ // Case 2: Content is a single object.
261+ contentParts = append (contentParts , singleContent )
262+ } else if sliceContent , ok := openAiMessage .Content .Value .([]openai.ChatCompletionAssistantMessageParamContent ); ok {
263+ // Case 3: Content is already a slice of objects.
264+ contentParts = sliceContent
265+ }
266+
267+ for _ , content := range contentParts {
268+ switch content .Type {
269+ case openai .ChatCompletionAssistantMessageParamContentTypeText :
270+ if content .Text != nil {
271+ contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {Text : content .Text })
272+ }
273+ case openai .ChatCompletionAssistantMessageParamContentTypeThinking :
274+ if content .Text != nil {
275+ reasoningText := & awsbedrock.ReasoningTextBlock {
276+ Text : * content .Text ,
277+ }
278+ if content .Signature != nil {
279+ reasoningText .Signature = * content .Signature
280+ }
281+ contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {
282+ ReasoningContent : & awsbedrock.ReasoningContentBlock {
283+ ReasoningText : reasoningText ,
284+ },
285+ })
286+ }
287+ case openai .ChatCompletionAssistantMessageParamContentTypeRedactedThinking :
288+ if content .RedactedContent != nil {
289+ contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {
290+ ReasoningContent : & awsbedrock.ReasoningContentBlock {
291+ RedactedContent : content .RedactedContent ,
292+ },
293+ })
294+ }
295+ case openai .ChatCompletionAssistantMessageParamContentTypeRefusal :
296+ if content .Refusal != nil {
297+ contentBlocks = append (contentBlocks , & awsbedrock.ContentBlock {Text : content .Refusal })
298+ }
259299 }
260300 }
261- bedrockMessage = & awsbedrock.Message {
262- Role : role ,
263- Content : contentBlocks ,
264- }
301+
302+ bedrockMessage .Content = contentBlocks
303+
265304 for i := range openAiMessage .ToolCalls {
266305 toolCall := & openAiMessage .ToolCalls [i ]
267306 input , err := unmarshalToolCallArguments (toolCall .Function .Arguments )
@@ -628,11 +667,11 @@ func (o *openAIToAWSBedrockTranslatorV1ChatCompletion) ResponseBody(_ map[string
628667 if choice .Message .Content == nil {
629668 choice .Message .Content = output .Text
630669 }
631- case output .ReasoningContent != nil && output . ReasoningContent . ReasoningText != nil :
670+ case output .ReasoningContent != nil :
632671 if choice .Message .AWSBedRockResponseVendorFields == nil {
633672 choice .Message .AWSBedRockResponseVendorFields = & openai.AWSBedRockResponseVendorFields {}
634673 }
635- choice .Message .ReasoningContent = output .ReasoningContent
674+ choice .Message .ReasoningContent = & openai. AWSBedRockReasoningContent { ReasoningContent : output .ReasoningContent }
636675 }
637676 }
638677 openAIResp .Choices = append (openAIResp .Choices , choice )
@@ -661,10 +700,7 @@ func (o *openAIToAWSBedrockTranslatorV1ChatCompletion) extractAmazonEventStreamE
661700 for {
662701 msg , err := dec .Decode (r , nil )
663702 if err != nil {
664- // When failed, we stop processing the events.
665- // Copy the unread bytes to the beginning of the buffer.
666- copy (o .bufferedBody , o .bufferedBody [lastRead :])
667- o .bufferedBody = o .bufferedBody [:len (o .bufferedBody )- int (lastRead )]
703+ o .bufferedBody = o .bufferedBody [lastRead :]
668704 return
669705 }
670706 var event awsbedrock.ConverseStreamEvent
@@ -700,15 +736,16 @@ func (o *openAIToAWSBedrockTranslatorV1ChatCompletion) convertEvent(event *awsbe
700736 })
701737 o .role = * event .Role
702738 case event .Delta != nil :
703- if event .Delta .Text != nil {
739+ switch {
740+ case event .Delta .Text != nil :
704741 chunk .Choices = append (chunk .Choices , openai.ChatCompletionResponseChunkChoice {
705742 Index : 0 ,
706743 Delta : & openai.ChatCompletionResponseChunkChoiceDelta {
707744 Role : o .role ,
708745 Content : event .Delta .Text ,
709746 },
710747 })
711- } else if event .Delta .ToolUse != nil {
748+ case event .Delta .ToolUse != nil :
712749 chunk .Choices = append (chunk .Choices , openai.ChatCompletionResponseChunkChoice {
713750 Index : 0 ,
714751 Delta : & openai.ChatCompletionResponseChunkChoiceDelta {
@@ -723,6 +760,25 @@ func (o *openAIToAWSBedrockTranslatorV1ChatCompletion) convertEvent(event *awsbe
723760 },
724761 },
725762 })
763+ case event .Delta .ReasoningContent != nil :
764+ reasoningDelta := & openai.AWSBedRockStreamReasoningContent {}
765+
766+ // Map all relevant fields from the Bedrock delta to our flattened OpenAI delta struct.
767+ if event .Delta .ReasoningContent .ReasoningText != nil {
768+ reasoningDelta .Text = event .Delta .ReasoningContent .ReasoningText .Text
769+ reasoningDelta .Signature = event .Delta .ReasoningContent .ReasoningText .Signature
770+ }
771+ if event .Delta .ReasoningContent .RedactedContent != nil {
772+ reasoningDelta .RedactedContent = event .Delta .ReasoningContent .RedactedContent
773+ }
774+
775+ chunk .Choices = append (chunk .Choices , openai.ChatCompletionResponseChunkChoice {
776+ Index : 0 ,
777+ Delta : & openai.ChatCompletionResponseChunkChoiceDelta {
778+ Role : o .role ,
779+ ReasoningContent : reasoningDelta ,
780+ },
781+ })
726782 }
727783 case event .Start != nil :
728784 if event .Start .ToolUse != nil {
0 commit comments