@@ -47,8 +47,31 @@ class UnsupportedModelError(Exception):
4747 pass
4848
4949
50- def chat (messages , copilot_token , model = "gpt-4o" , tools = None ):
51- payload = {"model" : model , "messages" : messages , "stream" : False }
50+ def _parse_sse (resp ):
51+ """Parse SSE stream from chat completions API, yielding content chunks."""
52+ for line in resp .iter_lines ():
53+ if not line :
54+ continue
55+ line = line .decode ("utf-8" ) if isinstance (line , bytes ) else line
56+ if not line .startswith ("data: " ):
57+ continue
58+ data = line [6 :]
59+ if data == "[DONE]" :
60+ break
61+ try :
62+ import json
63+
64+ chunk = json .loads (data )
65+ delta = chunk .get ("choices" , [{}])[0 ].get ("delta" , {})
66+ content = delta .get ("content" )
67+ if content :
68+ yield content
69+ except (ValueError , KeyError , IndexError ):
70+ continue
71+
72+
73+ def chat (messages , copilot_token , model = "gpt-4o" , tools = None , stream = False ):
74+ payload = {"model" : model , "messages" : messages , "stream" : stream }
5275 if tools :
5376 payload ["tools" ] = tools
5477 payload ["tool_choice" ] = "auto"
@@ -57,6 +80,7 @@ def chat(messages, copilot_token, model="gpt-4o", tools=None):
5780 f"{ COPILOT_API_BASE } /chat/completions" ,
5881 headers = {"Authorization" : f"Bearer { copilot_token } " , ** COPILOT_HEADERS },
5982 json = payload ,
83+ stream = stream ,
6084 )
6185 if not resp .ok :
6286 if resp .status_code == 400 and "unsupported_api_for_model" in resp .text :
@@ -66,4 +90,6 @@ def chat(messages, copilot_token, model="gpt-4o", tools=None):
6690 raise RuntimeError (
6791 f"Chat API error: { resp .status_code } { resp .reason } \n { resp .text } "
6892 )
93+ if stream :
94+ return _parse_sse (resp )
6995 return resp .json ()["choices" ][0 ]["message" ]
0 commit comments