summaryrefslogtreecommitdiffstats
path: root/g4f/Provider/needs_auth/GithubCopilot.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g4f/Provider/needs_auth/GithubCopilot.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/g4f/Provider/needs_auth/GithubCopilot.py b/g4f/Provider/needs_auth/GithubCopilot.py
new file mode 100644
index 00000000..0c12dfd0
--- /dev/null
+++ b/g4f/Provider/needs_auth/GithubCopilot.py
@@ -0,0 +1,93 @@
+from __future__ import annotations
+
+import json
+
+from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin, BaseConversation
+from ...typing import AsyncResult, Messages, Cookies
+from ...requests.raise_for_status import raise_for_status
+from ...requests import StreamSession
+from ...providers.helper import format_prompt
+from ...cookies import get_cookies
+
+class Conversation(BaseConversation):
+ conversation_id: str
+
+ def __init__(self, conversation_id: str):
+ self.conversation_id = conversation_id
+
+class GithubCopilot(AsyncGeneratorProvider, ProviderModelMixin):
+ url = "https://copilot.microsoft.com"
+ working = True
+ needs_auth = True
+ supports_stream = True
+ default_model = "gpt-4o"
+ models = [default_model, "o1-mini", "o1-preview", "claude-3.5-sonnet"]
+
+ @classmethod
+ async def create_async_generator(
+ cls,
+ model: str,
+ messages: Messages,
+ stream: bool = False,
+ api_key: str = "X2eRgXPamxGK_TXS6seGGYy541mQuVJdH1CYljrvSPuc38je5J4KK4Aw0y5X2oVRFMjA4B1fo9sdsr4VJcl-VBae7H0Mr4U9GIkFnGx3hSs=",
+ proxy: str = None,
+ cookies: Cookies = None,
+ conversation_id: str = None,
+ conversation: Conversation = None,
+ return_conversation: bool = False,
+ **kwargs
+ ) -> AsyncResult:
+ if not model:
+ model = cls.default_model
+ if cookies is None:
+ cookies = get_cookies(".github.com")
+ async with StreamSession(
+ proxy=proxy,
+ impersonate="chrome",
+ cookies=cookies,
+ headers={
+ "GitHub-Verified-Fetch": "true",
+ }
+ ) as session:
+ headers = {}
+ if api_key is None:
+ async with session.post("https://github.com/github-copilot/chat/token") as response:
+ await raise_for_status(response, "Get token")
+ api_key = (await response.json()).get("token")
+ headers = {
+ "Authorization": f"GitHub-Bearer {api_key}",
+ }
+ if conversation is not None:
+ conversation_id = conversation.conversation_id
+ if conversation_id is None:
+ print(headers)
+ async with session.post("https://api.individual.githubcopilot.com/github/chat/threads", headers=headers) as response:
+ await raise_for_status(response)
+ conversation_id = (await response.json()).get("thread_id")
+ if return_conversation:
+ yield Conversation(conversation_id)
+ content = messages[-1]["content"]
+ else:
+ content = format_prompt(messages)
+ json_data = {
+ "content": content,
+ "intent": "conversation",
+ "references":[],
+ "context": [],
+ "currentURL": f"https://github.com/copilot/c/{conversation_id}",
+ "streaming": True,
+ "confirmations": [],
+ "customInstructions": [],
+ "model": model,
+ "mode": "immersive"
+ }
+ async with session.post(
+ f"https://api.individual.githubcopilot.com/github/chat/threads/{conversation_id}/messages",
+ json=json_data,
+ headers=headers
+ ) as response:
+ async for line in response.iter_lines():
+ if line.startswith(b"data: "):
+ data = json.loads(line[6:])
+ if data.get("type") == "content":
+ yield data.get("body") \ No newline at end of file