@@ -37,6 +37,7 @@ func ClaudeReqToOpenAI(claudeReq []byte, model string) ([]byte, error) {
3737 var textParts []string
3838 var toolCalls []transformer.OpenAIToolCall
3939 var toolResults []transformer.OpenAIMessage
40+ hasThinking := false
4041
4142 for _ , block := range content {
4243 m , ok := block .(map [string ]interface {})
@@ -51,22 +52,35 @@ func ClaudeReqToOpenAI(claudeReq []byte, model string) ([]byte, error) {
5152 case "thinking" :
5253 // Skip thinking blocks - they are Claude's internal reasoning
5354 // and should not be forwarded to other APIs
55+ hasThinking = true
5456 continue
5557 case "tool_use" :
5658 args , _ := json .Marshal (m ["input" ])
59+ id , ok := m ["id" ].(string )
60+ if ! ok || id == "" {
61+ continue
62+ }
63+ name , ok := m ["name" ].(string )
64+ if ! ok || name == "" {
65+ continue
66+ }
5767 toolCalls = append (toolCalls , transformer.OpenAIToolCall {
58- ID : m [ "id" ].( string ) ,
68+ ID : id ,
5969 Type : "function" ,
6070 Function : struct {
6171 Name string `json:"name"`
6272 Arguments string `json:"arguments"`
63- }{Name : m [ " name" ].( string ) , Arguments : string (args )},
73+ }{Name : name , Arguments : string (args )},
6474 })
6575 case "tool_result" :
76+ callID , ok := m ["tool_use_id" ].(string )
77+ if ! ok || callID == "" {
78+ continue
79+ }
6680 toolResults = append (toolResults , transformer.OpenAIMessage {
6781 Role : "tool" ,
6882 Content : extractToolResultContent (m ["content" ]),
69- ToolCallID : m [ "tool_use_id" ].( string ) ,
83+ ToolCallID : callID ,
7084 })
7185 }
7286 }
@@ -81,6 +95,11 @@ func ClaudeReqToOpenAI(claudeReq []byte, model string) ([]byte, error) {
8195 openaiMsg .ToolCalls = toolCalls
8296 }
8397 messages = append (messages , openaiMsg )
98+ } else if hasThinking && msg .Role == "assistant" {
99+ messages = append (messages , transformer.OpenAIMessage {
100+ Role : "assistant" ,
101+ Content : "(thinking...)" ,
102+ })
84103 }
85104
86105 // Add tool result messages
@@ -317,7 +336,7 @@ func OpenAIRespToClaude(openaiResp []byte) ([]byte, error) {
317336 if len (resp .Choices ) > 0 {
318337 choice := resp .Choices [0 ]
319338 if choice .Message .Content != "" {
320- content = append (content , map [ string ] interface {}{ "type" : "text" , "text" : choice .Message .Content } )
339+ content = append (content , splitThinkTaggedText ( choice .Message .Content ) ... )
321340 }
322341 for _ , tc := range choice .Message .ToolCalls {
323342 var args map [string ]interface {}
@@ -428,6 +447,8 @@ func OpenAIStreamToClaude(event []byte, ctx *transformer.StreamContext) ([]byte,
428447 if jsonData == "" || jsonData == "[DONE]" {
429448 if jsonData == "[DONE]" {
430449 var result []byte
450+ emitText , emitThinking := makeThinkEmitters (ctx , & result )
451+ flushThinkTaggedStream (ctx , emitText , emitThinking )
431452 // Close any open content blocks before message_stop
432453 if ctx .ThinkingBlockStarted {
433454 result = append (result , buildClaudeEvent ("content_block_stop" , map [string ]interface {}{"index" : ctx .ThinkingIndex })... )
@@ -476,11 +497,34 @@ func OpenAIStreamToClaude(event []byte, ctx *transformer.StreamContext) ([]byte,
476497 }
477498
478499 if len (chunk .Choices ) == 0 {
500+ if chunk .Usage != nil {
501+ usageObj := map [string ]interface {}{
502+ "input_tokens" : chunk .Usage .PromptTokens ,
503+ "output_tokens" : chunk .Usage .CompletionTokens ,
504+ }
505+ msgDelta := map [string ]interface {}{
506+ "delta" : map [string ]interface {}{},
507+ "usage" : usageObj ,
508+ }
509+ result = append (result , buildClaudeEvent ("message_delta" , msgDelta )... )
510+ }
479511 return result , nil
480512 }
481513
482514 choice := chunk .Choices [0 ]
483515 delta := choice .Delta
516+ if chunk .Usage != nil && delta .Role == "" && delta .Content == "" && delta .ReasoningContent == "" && len (delta .ToolCalls ) == 0 && choice .FinishReason == nil {
517+ usageObj := map [string ]interface {}{
518+ "input_tokens" : chunk .Usage .PromptTokens ,
519+ "output_tokens" : chunk .Usage .CompletionTokens ,
520+ }
521+ msgDelta := map [string ]interface {}{
522+ "delta" : map [string ]interface {}{},
523+ "usage" : usageObj ,
524+ }
525+ result = append (result , buildClaudeEvent ("message_delta" , msgDelta )... )
526+ return result , nil
527+ }
484528
485529 // Reasoning/Thinking content (before text content)
486530 if delta .ReasoningContent != "" {
@@ -499,20 +543,32 @@ func OpenAIStreamToClaude(event []byte, ctx *transformer.StreamContext) ([]byte,
499543
500544 // Text content
501545 if delta .Content != "" {
502- // Close thinking block if transitioning to text
503- if ctx .ThinkingBlockStarted && ! ctx .ContentBlockStarted {
504- result = append (result , buildClaudeEvent ("content_block_stop" , map [string ]interface {}{"index" : ctx .ThinkingIndex })... )
505- ctx .ThinkingBlockStarted = false
546+ content := ctx .ThinkingBuffer + delta .Content
547+ ctx .ThinkingBuffer = ""
548+
549+ emitText , emitThinking := makeThinkEmitters (ctx , & result )
550+ emitTextWithClose := func (text string ) {
551+ if text == "" {
552+ return
553+ }
554+ if ctx .ThinkingBlockStarted && ! ctx .ContentBlockStarted && ! ctx .InThinkingTag {
555+ result = append (result , buildClaudeEvent ("content_block_stop" , map [string ]interface {}{"index" : ctx .ThinkingIndex })... )
556+ ctx .ThinkingBlockStarted = false
557+ }
558+ emitText (text )
506559 }
507- if ! ctx .ContentBlockStarted {
508- ctx .ContentBlockStarted = true
509- result = append (result , buildClaudeEvent ("content_block_start" , map [string ]interface {}{
510- "index" : ctx .ContentIndex , "content_block" : map [string ]interface {}{"type" : "text" , "text" : "" },
511- })... )
560+ emitThinkingWithClose := func (text string ) {
561+ if text == "" {
562+ return
563+ }
564+ emitThinking (text )
565+ if ctx .ThinkingBlockStarted {
566+ result = append (result , buildClaudeEvent ("content_block_stop" , map [string ]interface {}{"index" : ctx .ThinkingIndex })... )
567+ ctx .ThinkingBlockStarted = false
568+ }
512569 }
513- result = append (result , buildClaudeEvent ("content_block_delta" , map [string ]interface {}{
514- "index" : ctx .ContentIndex , "delta" : map [string ]interface {}{"type" : "text_delta" , "text" : delta .Content },
515- })... )
570+
571+ consumeThinkTaggedStream (content , ctx , emitTextWithClose , emitThinkingWithClose )
516572 }
517573
518574 // Tool calls
@@ -667,4 +723,3 @@ func extractToolResultContent(content interface{}) string {
667723 }
668724 return ""
669725}
670-
0 commit comments