77package claude
88
99import (
10- "bufio"
1110 "bytes"
1211 "context"
1312 "encoding/json"
@@ -180,56 +179,58 @@ func ConvertCodexResponseToClaude(_ context.Context, _ string, originalRequestRa
180179// Returns:
181180// - string: A Claude Code-compatible JSON response containing all message content and metadata
182181func ConvertCodexResponseToClaudeNonStream (_ context.Context , _ string , originalRequestRawJSON , _ []byte , rawJSON []byte , _ * any ) string {
183- scanner := bufio .NewScanner (bytes .NewReader (rawJSON ))
184- buffer := make ([]byte , 20_971_520 )
185- scanner .Buffer (buffer , 20_971_520 )
186182 revNames := buildReverseMapFromClaudeOriginalShortToOriginal (originalRequestRawJSON )
187183
188- for scanner .Scan () {
189- line := scanner .Bytes ()
190- if ! bytes .HasPrefix (line , dataTag ) {
191- continue
192- }
193- payload := bytes .TrimSpace (line [len (dataTag ):])
194- if len (payload ) == 0 {
195- continue
196- }
197-
198- rootResult := gjson .ParseBytes (payload )
199- if rootResult .Get ("type" ).String () != "response.completed" {
200- continue
201- }
202-
203- responseData := rootResult .Get ("response" )
204- if ! responseData .Exists () {
205- continue
206- }
184+ rootResult := gjson .ParseBytes (rawJSON )
185+ if rootResult .Get ("type" ).String () != "response.completed" {
186+ return ""
187+ }
207188
208- response := map [string ]interface {}{
209- "id" : responseData .Get ("id" ).String (),
210- "type" : "message" ,
211- "role" : "assistant" ,
212- "model" : responseData .Get ("model" ).String (),
213- "content" : []interface {}{},
214- "stop_reason" : nil ,
215- "stop_sequence" : nil ,
216- "usage" : map [string ]interface {}{
217- "input_tokens" : responseData .Get ("usage.input_tokens" ).Int (),
218- "output_tokens" : responseData .Get ("usage.output_tokens" ).Int (),
219- },
220- }
189+ responseData := rootResult .Get ("response" )
190+ if ! responseData .Exists () {
191+ return ""
192+ }
221193
222- var contentBlocks []interface {}
223- hasToolCall := false
194+ response := map [string ]interface {}{
195+ "id" : responseData .Get ("id" ).String (),
196+ "type" : "message" ,
197+ "role" : "assistant" ,
198+ "model" : responseData .Get ("model" ).String (),
199+ "content" : []interface {}{},
200+ "stop_reason" : nil ,
201+ "stop_sequence" : nil ,
202+ "usage" : map [string ]interface {}{
203+ "input_tokens" : responseData .Get ("usage.input_tokens" ).Int (),
204+ "output_tokens" : responseData .Get ("usage.output_tokens" ).Int (),
205+ },
206+ }
224207
225- if output := responseData .Get ("output" ); output .Exists () && output .IsArray () {
226- output .ForEach (func (_ , item gjson.Result ) bool {
227- switch item .Get ("type" ).String () {
228- case "reasoning" :
229- thinkingBuilder := strings.Builder {}
230- if summary := item .Get ("summary" ); summary .Exists () {
231- if summary .IsArray () {
232- summary .ForEach (func (_ , part gjson.Result ) bool {
208+ var contentBlocks []interface {}
209+ hasToolCall := false
210+
211+ if output := responseData .Get ("output" ); output .Exists () && output .IsArray () {
212+ output .ForEach (func (_ , item gjson.Result ) bool {
213+ switch item .Get ("type" ).String () {
214+ case "reasoning" :
215+ thinkingBuilder := strings.Builder {}
216+ if summary := item .Get ("summary" ); summary .Exists () {
217+ if summary .IsArray () {
218+ summary .ForEach (func (_ , part gjson.Result ) bool {
219+ if txt := part .Get ("text" ); txt .Exists () {
220+ thinkingBuilder .WriteString (txt .String ())
221+ } else {
222+ thinkingBuilder .WriteString (part .String ())
223+ }
224+ return true
225+ })
226+ } else {
227+ thinkingBuilder .WriteString (summary .String ())
228+ }
229+ }
230+ if thinkingBuilder .Len () == 0 {
231+ if content := item .Get ("content" ); content .Exists () {
232+ if content .IsArray () {
233+ content .ForEach (func (_ , part gjson.Result ) bool {
233234 if txt := part .Get ("text" ); txt .Exists () {
234235 thinkingBuilder .WriteString (txt .String ())
235236 } else {
@@ -238,114 +239,96 @@ func ConvertCodexResponseToClaudeNonStream(_ context.Context, _ string, original
238239 return true
239240 })
240241 } else {
241- thinkingBuilder .WriteString (summary .String ())
242+ thinkingBuilder .WriteString (content .String ())
242243 }
243244 }
244- if thinkingBuilder .Len () == 0 {
245- if content := item .Get ("content" ); content .Exists () {
246- if content .IsArray () {
247- content .ForEach (func (_ , part gjson.Result ) bool {
248- if txt := part .Get ("text" ); txt .Exists () {
249- thinkingBuilder .WriteString (txt .String ())
250- } else {
251- thinkingBuilder .WriteString (part .String ())
252- }
253- return true
254- })
255- } else {
256- thinkingBuilder .WriteString (content .String ())
245+ }
246+ if thinkingBuilder .Len () > 0 {
247+ contentBlocks = append (contentBlocks , map [string ]interface {}{
248+ "type" : "thinking" ,
249+ "thinking" : thinkingBuilder .String (),
250+ })
251+ }
252+ case "message" :
253+ if content := item .Get ("content" ); content .Exists () {
254+ if content .IsArray () {
255+ content .ForEach (func (_ , part gjson.Result ) bool {
256+ if part .Get ("type" ).String () == "output_text" {
257+ text := part .Get ("text" ).String ()
258+ if text != "" {
259+ contentBlocks = append (contentBlocks , map [string ]interface {}{
260+ "type" : "text" ,
261+ "text" : text ,
262+ })
263+ }
257264 }
258- }
259- }
260- if thinkingBuilder .Len () > 0 {
261- contentBlocks = append (contentBlocks , map [string ]interface {}{
262- "type" : "thinking" ,
263- "thinking" : thinkingBuilder .String (),
265+ return true
264266 })
265- }
266- case "message" :
267- if content := item .Get ("content" ); content .Exists () {
268- if content .IsArray () {
269- content .ForEach (func (_ , part gjson.Result ) bool {
270- if part .Get ("type" ).String () == "output_text" {
271- text := part .Get ("text" ).String ()
272- if text != "" {
273- contentBlocks = append (contentBlocks , map [string ]interface {}{
274- "type" : "text" ,
275- "text" : text ,
276- })
277- }
278- }
279- return true
267+ } else {
268+ text := content .String ()
269+ if text != "" {
270+ contentBlocks = append (contentBlocks , map [string ]interface {}{
271+ "type" : "text" ,
272+ "text" : text ,
280273 })
281- } else {
282- text := content .String ()
283- if text != "" {
284- contentBlocks = append (contentBlocks , map [string ]interface {}{
285- "type" : "text" ,
286- "text" : text ,
287- })
288- }
289274 }
290275 }
291- case "function_call" :
292- hasToolCall = true
293- name := item .Get ("name" ).String ()
294- if original , ok := revNames [name ]; ok {
295- name = original
296- }
276+ }
277+ case "function_call" :
278+ hasToolCall = true
279+ name := item .Get ("name" ).String ()
280+ if original , ok := revNames [name ]; ok {
281+ name = original
282+ }
297283
298- toolBlock := map [string ]interface {}{
299- "type" : "tool_use" ,
300- "id" : item .Get ("call_id" ).String (),
301- "name" : name ,
302- "input" : map [string ]interface {}{},
303- }
284+ toolBlock := map [string ]interface {}{
285+ "type" : "tool_use" ,
286+ "id" : item .Get ("call_id" ).String (),
287+ "name" : name ,
288+ "input" : map [string ]interface {}{},
289+ }
304290
305- if argsStr := item .Get ("arguments" ).String (); argsStr != "" {
306- var args interface {}
307- if err := json .Unmarshal ([]byte (argsStr ), & args ); err == nil {
308- toolBlock ["input" ] = args
309- }
291+ if argsStr := item .Get ("arguments" ).String (); argsStr != "" {
292+ var args interface {}
293+ if err := json .Unmarshal ([]byte (argsStr ), & args ); err == nil {
294+ toolBlock ["input" ] = args
310295 }
311-
312- contentBlocks = append (contentBlocks , toolBlock )
313296 }
314- return true
315- })
316- }
317297
318- if len (contentBlocks ) > 0 {
319- response ["content" ] = contentBlocks
320- }
298+ contentBlocks = append (contentBlocks , toolBlock )
299+ }
300+ return true
301+ })
302+ }
321303
322- if stopReason := responseData .Get ("stop_reason" ); stopReason .Exists () && stopReason .String () != "" {
323- response ["stop_reason" ] = stopReason .String ()
324- } else if hasToolCall {
325- response ["stop_reason" ] = "tool_use"
326- } else {
327- response ["stop_reason" ] = "end_turn"
328- }
304+ if len (contentBlocks ) > 0 {
305+ response ["content" ] = contentBlocks
306+ }
329307
330- if stopSequence := responseData .Get ("stop_sequence" ); stopSequence .Exists () && stopSequence .String () != "" {
331- response ["stop_sequence" ] = stopSequence .Value ()
332- }
308+ if stopReason := responseData .Get ("stop_reason" ); stopReason .Exists () && stopReason .String () != "" {
309+ response ["stop_reason" ] = stopReason .String ()
310+ } else if hasToolCall {
311+ response ["stop_reason" ] = "tool_use"
312+ } else {
313+ response ["stop_reason" ] = "end_turn"
314+ }
333315
334- if responseData .Get ("usage.input_tokens" ).Exists () || responseData .Get ("usage.output_tokens" ).Exists () {
335- response ["usage" ] = map [string ]interface {}{
336- "input_tokens" : responseData .Get ("usage.input_tokens" ).Int (),
337- "output_tokens" : responseData .Get ("usage.output_tokens" ).Int (),
338- }
339- }
316+ if stopSequence := responseData .Get ("stop_sequence" ); stopSequence .Exists () && stopSequence .String () != "" {
317+ response ["stop_sequence" ] = stopSequence .Value ()
318+ }
340319
341- responseJSON , err := json .Marshal (response )
342- if err != nil {
343- return ""
320+ if responseData .Get ("usage.input_tokens" ).Exists () || responseData .Get ("usage.output_tokens" ).Exists () {
321+ response ["usage" ] = map [string ]interface {}{
322+ "input_tokens" : responseData .Get ("usage.input_tokens" ).Int (),
323+ "output_tokens" : responseData .Get ("usage.output_tokens" ).Int (),
344324 }
345- return string (responseJSON )
346325 }
347326
348- return ""
327+ responseJSON , err := json .Marshal (response )
328+ if err != nil {
329+ return ""
330+ }
331+ return string (responseJSON )
349332}
350333
351334// buildReverseMapFromClaudeOriginalShortToOriginal builds a map[short]original from original Claude request tools.
0 commit comments