@@ -26,7 +26,7 @@ pub struct OpenAiCodexProvider {
2626 client : Client ,
2727}
2828
29- #[ derive( Debug , Serialize ) ]
29+ #[ derive( Debug , Serialize , Clone ) ]
3030struct ResponsesRequest {
3131 model : String ,
3232 input : Vec < ResponsesInput > ,
@@ -40,13 +40,13 @@ struct ResponsesRequest {
4040 parallel_tool_calls : bool ,
4141}
4242
43- #[ derive( Debug , Serialize ) ]
43+ #[ derive( Debug , Serialize , Clone ) ]
4444struct ResponsesInput {
4545 role : String ,
4646 content : Vec < ResponsesInputContent > ,
4747}
4848
49- #[ derive( Debug , Serialize ) ]
49+ #[ derive( Debug , Serialize , Clone ) ]
5050struct ResponsesInputContent {
5151 #[ serde( rename = "type" ) ]
5252 kind : String ,
@@ -56,12 +56,12 @@ struct ResponsesInputContent {
5656 image_url : Option < String > ,
5757}
5858
59- #[ derive( Debug , Serialize ) ]
59+ #[ derive( Debug , Serialize , Clone ) ]
6060struct ResponsesTextOptions {
6161 verbosity : String ,
6262}
6363
64- #[ derive( Debug , Serialize ) ]
64+ #[ derive( Debug , Serialize , Clone ) ]
6565struct ResponsesReasoningOptions {
6666 effort : String ,
6767 summary : String ,
@@ -711,7 +711,54 @@ impl OpenAiCodexProvider {
711711 return Err ( super :: api_error ( "OpenAI Codex" , response) . await ) ;
712712 }
713713
714- decode_responses_body ( response) . await
714+ // Try to decode streaming response first
715+ match decode_responses_body ( response) . await {
716+ Ok ( text) => Ok ( text) ,
717+ // If streaming fails, retry with non-streaming request
718+ Err ( e) => {
719+ tracing:: warn!(
720+ error = %e,
721+ "OpenAI Codex streaming failed, retrying with non-streaming request"
722+ ) ;
723+ let mut non_streaming_request = request. clone ( ) ;
724+ non_streaming_request. stream = false ;
725+
726+ let mut non_streaming_builder = self
727+ . client
728+ . post ( & self . responses_url )
729+ . header ( "Authorization" , format ! ( "Bearer {bearer_token}" ) )
730+ . header ( "OpenAI-Beta" , "responses=experimental" )
731+ . header ( "originator" , "pi" )
732+ . header ( "Content-Type" , "application/json" ) ;
733+
734+ if let Some ( account_id) = account_id. as_deref ( ) {
735+ non_streaming_builder =
736+ non_streaming_builder. header ( "chatgpt-account-id" , account_id) ;
737+ }
738+
739+ if use_gateway_api_key_auth {
740+ if let Some ( access_token) = access_token. as_deref ( ) {
741+ non_streaming_builder =
742+ non_streaming_builder. header ( "x-openai-access-token" , access_token) ;
743+ }
744+ if let Some ( account_id) = account_id. as_deref ( ) {
745+ non_streaming_builder =
746+ non_streaming_builder. header ( "x-openai-account-id" , account_id) ;
747+ }
748+ }
749+
750+ let non_streaming_response = non_streaming_builder
751+ . json ( & non_streaming_request)
752+ . send ( )
753+ . await ?;
754+
755+ if !non_streaming_response. status ( ) . is_success ( ) {
756+ return Err ( super :: api_error ( "OpenAI Codex" , non_streaming_response) . await ) ;
757+ }
758+
759+ decode_responses_body ( non_streaming_response) . await
760+ }
761+ }
715762 }
716763}
717764
0 commit comments