@@ -794,6 +794,79 @@ def convert_to_azure_payload(url, payload: dict, api_version: str):
794794 return url , payload
795795
796796
797+ def convert_to_responses_payload (payload : dict ) -> dict :
798+ """
799+ Convert Chat Completions payload to Responses API format.
800+
801+ Chat Completions: { messages: [{role, content}], ... }
802+ Responses API: { input: [{type: "message", role, content: [...]}], instructions: "system" }
803+ """
804+ messages = payload .pop ("messages" , [])
805+
806+ system_content = ""
807+ input_items = []
808+
809+ for msg in messages :
810+ role = msg .get ("role" , "user" )
811+ content = msg .get ("content" , "" )
812+
813+ # Check for stored output items (from previous Responses API turn)
814+ stored_output = msg .get ("output" )
815+ if stored_output and isinstance (stored_output , list ):
816+ input_items .extend (stored_output )
817+ continue
818+
819+ if role == "system" :
820+ if isinstance (content , str ):
821+ system_content = content
822+ elif isinstance (content , list ):
823+ system_content = "\n " .join (p .get ("text" , "" ) for p in content if p .get ("type" ) == "text" )
824+ continue
825+
826+ # Convert content format
827+ text_type = "output_text" if role == "assistant" else "input_text"
828+
829+ if isinstance (content , str ):
830+ content_parts = [{"type" : text_type , "text" : content }]
831+ elif isinstance (content , list ):
832+ content_parts = []
833+ for part in content :
834+ if part .get ("type" ) == "text" :
835+ content_parts .append ({"type" : text_type , "text" : part .get ("text" , "" )})
836+ elif part .get ("type" ) == "image_url" :
837+ url_data = part .get ("image_url" , {})
838+ url = url_data .get ("url" , "" ) if isinstance (url_data , dict ) else url_data
839+ content_parts .append ({"type" : "input_image" , "image_url" : url })
840+ else :
841+ content_parts = [{"type" : text_type , "text" : str (content )}]
842+
843+ input_items .append ({
844+ "type" : "message" ,
845+ "role" : role ,
846+ "content" : content_parts
847+ })
848+
849+ responses_payload = {** payload , "input" : input_items }
850+
851+ if system_content :
852+ responses_payload ["instructions" ] = system_content
853+
854+ if "max_tokens" in responses_payload :
855+ responses_payload ["max_output_tokens" ] = responses_payload .pop ("max_tokens" )
856+
857+ return responses_payload
858+
859+
860+
861+ def convert_responses_result (response : dict ) -> dict :
862+ """
863+ Convert non-streaming Responses API result.
864+ Just add done flag - pass through raw response, frontend handles output.
865+ """
866+ response ["done" ] = True
867+ return response
868+
869+
797870@router .post ("/chat/completions" )
798871async def generate_chat_completion (
799872 request : Request ,
@@ -915,6 +988,8 @@ async def generate_chat_completion(
915988 request , url , key , api_config , metadata , user = user
916989 )
917990
991+ is_responses = api_config .get ("api_type" ) == "responses"
992+
918993 if api_config .get ("azure" , False ):
919994 api_version = api_config .get ("api_version" , "2023-03-15-preview" )
920995 request_url , payload = convert_to_azure_payload (url , payload , api_version )
@@ -925,9 +1000,18 @@ async def generate_chat_completion(
9251000 headers ["api-key" ] = key
9261001
9271002 headers ["api-version" ] = api_version
928- request_url = f"{ request_url } /chat/completions?api-version={ api_version } "
1003+
1004+ if is_responses :
1005+ payload = convert_to_responses_payload (payload )
1006+ request_url = f"{ request_url } /responses?api-version={ api_version } "
1007+ else :
1008+ request_url = f"{ request_url } /chat/completions?api-version={ api_version } "
9291009 else :
930- request_url = f"{ url } /chat/completions"
1010+ if is_responses :
1011+ payload = convert_to_responses_payload (payload )
1012+ request_url = f"{ url } /responses"
1013+ else :
1014+ request_url = f"{ url } /chat/completions"
9311015
9321016 payload = json .dumps (payload )
9331017
@@ -974,6 +1058,10 @@ async def generate_chat_completion(
9741058 else :
9751059 return PlainTextResponse (status_code = r .status , content = response )
9761060
1061+ # Convert Responses API result to simple format
1062+ if is_responses and isinstance (response , dict ):
1063+ response = convert_responses_result (response )
1064+
9771065 return response
9781066 except Exception as e :
9791067 log .exception (e )
0 commit comments