@@ -68,36 +68,79 @@ func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool)
6868
6969 for i := 0 ; i < len (messageResults ); i ++ {
7070 messageResult := messageResults [i ]
71+ messageRole := messageResult .Get ("role" ).String ()
72+
73+ newMessage := func () string {
74+ msg := `{"type": "message","role":"","content":[]}`
75+ msg , _ = sjson .Set (msg , "role" , messageRole )
76+ return msg
77+ }
78+
79+ message := newMessage ()
80+ contentIndex := 0
81+ hasContent := false
82+
83+ flushMessage := func () {
84+ if hasContent {
85+ template , _ = sjson .SetRaw (template , "input.-1" , message )
86+ message = newMessage ()
87+ contentIndex = 0
88+ hasContent = false
89+ }
90+ }
91+
92+ appendTextContent := func (text string ) {
93+ partType := "input_text"
94+ if messageRole == "assistant" {
95+ partType = "output_text"
96+ }
97+ message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.type" , contentIndex ), partType )
98+ message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.text" , contentIndex ), text )
99+ contentIndex ++
100+ hasContent = true
101+ }
102+
103+ appendImageContent := func (dataURL string ) {
104+ message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.type" , contentIndex ), "input_image" )
105+ message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.image_url" , contentIndex ), dataURL )
106+ contentIndex ++
107+ hasContent = true
108+ }
71109
72110 messageContentsResult := messageResult .Get ("content" )
73111 if messageContentsResult .IsArray () {
74112 messageContentResults := messageContentsResult .Array ()
75113 for j := 0 ; j < len (messageContentResults ); j ++ {
76114 messageContentResult := messageContentResults [j ]
77- messageContentTypeResult := messageContentResult .Get ("type" )
78- contentType := messageContentTypeResult .String ()
79-
80- if contentType == "text" {
81- // Handle text content by creating appropriate message structure.
82- message := `{"type": "message","role":"","content":[]}`
83- messageRole := messageResult .Get ("role" ).String ()
84- message , _ = sjson .Set (message , "role" , messageRole )
115+ contentType := messageContentResult .Get ("type" ).String ()
85116
86- partType := "input_text"
87- if messageRole == "assistant" {
88- partType = "output_text"
117+ switch contentType {
118+ case "text" :
119+ appendTextContent (messageContentResult .Get ("text" ).String ())
120+ case "image" :
121+ sourceResult := messageContentResult .Get ("source" )
122+ if sourceResult .Exists () {
123+ data := sourceResult .Get ("data" ).String ()
124+ if data == "" {
125+ data = sourceResult .Get ("base64" ).String ()
126+ }
127+ if data != "" {
128+ mediaType := sourceResult .Get ("media_type" ).String ()
129+ if mediaType == "" {
130+ mediaType = sourceResult .Get ("mime_type" ).String ()
131+ }
132+ if mediaType == "" {
133+ mediaType = "application/octet-stream"
134+ }
135+ dataURL := fmt .Sprintf ("data:%s;base64,%s" , mediaType , data )
136+ appendImageContent (dataURL )
137+ }
89138 }
90-
91- currentIndex := len (gjson .Get (message , "content" ).Array ())
92- message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.type" , currentIndex ), partType )
93- message , _ = sjson .Set (message , fmt .Sprintf ("content.%d.text" , currentIndex ), messageContentResult .Get ("text" ).String ())
94- template , _ = sjson .SetRaw (template , "input.-1" , message )
95- } else if contentType == "tool_use" {
96- // Handle tool use content by creating function call message.
139+ case "tool_use" :
140+ flushMessage ()
97141 functionCallMessage := `{"type":"function_call"}`
98142 functionCallMessage , _ = sjson .Set (functionCallMessage , "call_id" , messageContentResult .Get ("id" ).String ())
99143 {
100- // Shorten tool name if needed based on declared tools
101144 name := messageContentResult .Get ("name" ).String ()
102145 toolMap := buildReverseMapFromClaudeOriginalToShort (rawJSON )
103146 if short , ok := toolMap [name ]; ok {
@@ -109,28 +152,18 @@ func ConvertClaudeRequestToCodex(modelName string, inputRawJSON []byte, _ bool)
109152 }
110153 functionCallMessage , _ = sjson .Set (functionCallMessage , "arguments" , messageContentResult .Get ("input" ).Raw )
111154 template , _ = sjson .SetRaw (template , "input.-1" , functionCallMessage )
112- } else if contentType == "tool_result" {
113- // Handle tool result content by creating function call output message.
155+ case "tool_result" :
156+ flushMessage ()
114157 functionCallOutputMessage := `{"type":"function_call_output"}`
115158 functionCallOutputMessage , _ = sjson .Set (functionCallOutputMessage , "call_id" , messageContentResult .Get ("tool_use_id" ).String ())
116159 functionCallOutputMessage , _ = sjson .Set (functionCallOutputMessage , "output" , messageContentResult .Get ("content" ).String ())
117160 template , _ = sjson .SetRaw (template , "input.-1" , functionCallOutputMessage )
118161 }
119162 }
163+ flushMessage ()
120164 } else if messageContentsResult .Type == gjson .String {
121- // Handle string content by creating appropriate message structure.
122- message := `{"type": "message","role":"","content":[]}`
123- messageRole := messageResult .Get ("role" ).String ()
124- message , _ = sjson .Set (message , "role" , messageRole )
125-
126- partType := "input_text"
127- if messageRole == "assistant" {
128- partType = "output_text"
129- }
130-
131- message , _ = sjson .Set (message , "content.0.type" , partType )
132- message , _ = sjson .Set (message , "content.0.text" , messageContentsResult .String ())
133- template , _ = sjson .SetRaw (template , "input.-1" , message )
165+ appendTextContent (messageContentsResult .String ())
166+ flushMessage ()
134167 }
135168 }
136169
0 commit comments