Copilot 令çèªå¨å·æ°å®æ¤è¿ç¨ | AIçæåç¿»è¯
ä¼è¯ ID: ses_31a4979a7ffe9rU42KDzISEti3 å建æ¶é´: 3/13/2026, 1:41:10 PM æ´æ°æ¶é´: 3/13/2026, 1:41:26 PM
ç¨æ·
like this , import threading
copilot_token_cache = {âtokenâ: None, âexpires_atâ: 0}
def refresh_copilot_token_loop(github_token: str): â"âBackground thread: auto-refresh Copilot token before expiryâââ while True: token_data = get_copilot_token(github_token) copilot_token_cache[âtokenâ] = token_data[âtokenâ] copilot_token_cache[âexpires_atâ] = token_data[âexpires_atâ]
refresh_in = token_data.get("refresh_in", 1500)
sleep_seconds = max(refresh_in - 60, 30) # refresh 60s before expiry
print(f"ð Next Copilot token refresh in {sleep_seconds}s")
time.sleep(sleep_seconds)
def start_token_refresh_daemon(github_token: str): thread = threading.Thread( target=refresh_copilot_token_loop, args=(github_token,), daemon=True ) thread.start() , import os
GITHUB_TOKEN_FILE = os.path.expanduser(â~/.copilot_github_tokenâ)
def load_or_auth_github_token() -> str: â"âLoad saved token or run device flowâââ if os.path.exists(GITHUB_TOKEN_FILE): with open(GITHUB_TOKEN_FILE) as f: token = f.read().strip() if token: print(ââ Loaded saved GitHub token.â) return token
# Run device flow
device_data = get_device_code()
github_token = poll_for_access_token(
device_data["device_code"],
interval=device_data.get("interval", 5)
)
# Persist token securely (chmod 600)
with open(GITHUB_TOKEN_FILE, "w") as f:
f.write(github_token)
os.chmod(GITHUB_TOKEN_FILE, 0o600)
return github_token
def main(): github_token = load_or_auth_github_token()
# Get initial Copilot token
token_data = get_copilot_token(github_token)
copilot_token_cache["token"] = token_data["token"]
copilot_token_cache["expires_at"] = token_data["expires_at"]
# Start background refresh
start_token_refresh_daemon(github_token)
# Now call the LLM
answer = call_copilot_llm("What is GitHub Copilot?")
print("ð¤ Copilot says:", answer)
if name == âmainâ: main() , also add refresh token logic
婿 (Build · google/gemini-3-flash-preview · 16.3s)
æèï¼
åæè®¤è¯çç¥
æç®å䏿³¨äºåææä¾ç代ç çæ®µï¼ä»¥çè§£æè®®çè®¤è¯æµç¨ï¼ç¹å«æ¯ârefresh token logicâãæç峿¶ä»»å¡æ¯æ¾åºå¦ä½æå¥½å°å°è¿äºé¨åæ´åæä¸ä¸ªè¿è´¯ç Python èæ¬ï¼è¯¥èæ¬å¯é å°ç®¡ç GitHub Copilot 认è¯ï¼éç¹å ³æ³¨ token å·æ°æºå¶çç¨³å¥æ§ã
ä¼å Copilot Token 管ç
æç°å¨ä¸æ³¨äºå°æä¾ç refresh token logic æ´åå°ä¸ä¸ªå ¨é¢ç Copilot 认è¯ç»æä¸ãæçéç¹æ¯åæä¸ä¸ªå®æ´ç Python å®ç°ï¼è¯¥å®ç°åºå 嫿æå¿ è¦é¨åï¼å¦ GitHub token å¤çå Copilot token 交æ¢ãæè¿å¨æ·»å ç¹å«è¯·æ±çåè½ï¼å¹¶å¤çè¿å access token çé»è¾ã
æå°å®ç°ä¸ä¸ª Python èæ¬ï¼æ´å GitHub Device Flow è¿è¡è®¤è¯ï¼å¤ç Copilot token 交æ¢ï¼å¹¶ç»´æ¤åå°å·æ°å¾ªç¯ï¼å¦è¯·æ±æè¿°ã
å®ç°è®¡å
- è®¤è¯æµç¨ï¼ä½¿ç¨ GitHub ç OAuth API å®ç°
get_device_codeåpoll_for_access_tokenã - Token 交æ¢ï¼å®ç°
get_copilot_tokenä»¥å° GitHub OAuth token 交æ¢ä¸ºä¸´æ¶ç Copilot ä¼è¯ tokenã - LLM 交äºï¼å®ç°
call_copilot_llm以æ¼ç¤ºä½¿ç¨ç¼å token ä¸ Copilot API ç交äºã - åå°å·æ°ï¼æ´åæ¨æä¾ç
threadingé»è¾ï¼ä»¥æ éæä¿æ Copilot token ææã
æå°ä»å建 copilot_proxy.py èæ¬å¼å§ã
copilot_proxy.py
import os
import time
import json
import threading
import requests
# Constants
GITHUB_TOKEN_FILE = os.path.expanduser("~/.copilot_github_token")
DEVICE_CODE_URL = "https://github.com/login/device/code"
ACCESS_TOKEN_URL = "https://github.com/login/oauth/access_token"
COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token"
COPILOT_CHAT_URL = "https://api.githubcopilot.com/chat/completions"
CLIENT_ID = "Iv1.b507a3d205f504c4" # GitHub CLI Client ID
# Global Cache
copilot_token_cache = {"token": None, "expires_at": 0}
def get_device_code():
"""Request a device code from GitHub"""
response = requests.post(
DEVICE_CODE_URL,
headers={"Accept": "application/json"},
data={"client_id": CLIENT_ID, "scope": "read:user"}
)
response.raise_for_status()
data = response.json()
print(f"ð Please visit: {data['verification_uri']}")
print(f"ð¢ Enter code: {data['user_code']}")
return data
def poll_for_access_token(device_code, interval):
"""Poll GitHub for the access token after user authorization"""
print("â³ Waiting for authorization...")
while True:
response = requests.post(
ACCESS_TOKEN_URL,
headers={"Accept": "application/json"},
data={
"client_id": CLIENT_ID,
"device_code": device_code,
"grant_type": "urn:ietf:params:oauth:grant-type:device_code"
}
)
data = response.json()
if "access_token" in data:
return data["access_token"]
error = data.get("error")
if error == "authorization_pending":
time.sleep(interval)
elif error == "slow_down":
time.sleep(interval + 5)
else:
raise Exception(f"Failed to get token: {data.get('error_description')}")
def get_copilot_token(github_token):
"""Exchange GitHub token for a Copilot session token"""
response = requests.get(
COPILOT_TOKEN_URL,
headers={
"Authorization": f"token {github_token}",
"Accept": "application/json",
}
)
response.raise_for_status()
return response.json()
def refresh_copilot_token_loop(github_token: str):
"""Background thread: auto-refresh Copilot token before expiry"""
while True:
try:
token_data = get_copilot_token(github_token)
copilot_token_cache["token"] = token_data["token"]
copilot_token_cache["expires_at"] = token_data["expires_at"]
refresh_in = token_data.get("refresh_in", 1500)
# Refresh 60s before expiry, but at least every 30s
sleep_seconds = max(refresh_in - 60, 30)
print(f"ð Next Copilot token refresh in {sleep_seconds}s")
time.sleep(sleep_seconds)
except Exception as e:
print(f"â Token refresh failed: {e}")
time.sleep(10) # Retry soon on failure
def start_token_refresh_daemon(github_token: str):
thread = threading.Thread(
target=refresh_copilot_token_loop,
args=(github_token,),
daemon=True
)
thread.start()
def load_or_auth_github_token() -> str:
"""Load saved token or run device flow"""
if os.path.exists(GITHUB_TOKEN_FILE):
with open(GITHUB_TOKEN_FILE) as f:
token = f.read().strip()
if token:
# Basic validation: check if token still works
try:
get_copilot_token(token)
print("â
Loaded saved GitHub token.")
return token
except:
print("â ï¸ Saved token invalid. Re-authenticating...")
device_data = get_device_code()
github_token = poll_for_access_token(
device_data["device_code"],
interval=device_data.get("interval", 5)
)
with open(GITHUB_TOKEN_FILE, "w") as f:
f.write(github_token)
os.chmod(GITHUB_TOKEN_FILE, 0o600)
return github_token
def call_copilot_llm(prompt: str):
"""Make a request to the Copilot Chat API using the cached token"""
if not copilot_token_cache["token"]:
raise Exception("Copilot token not available")
response = requests.post(
COPILOT_CHAT_URL,
headers={
"Authorization": f"Bearer {copilot_token_cache['token']}",
"Content-Type": "application/json",
"Editor-Version": "vscode/1.80.0",
},
json={
"messages": [{"role": "user", "content": prompt}],
"model": "gpt-4"
}
)
response.raise_for_status()
return response.json()["choices"][0]["message"]["content"]
def main():
try:
github_token = load_or_auth_github_token()
# Get initial Copilot token
token_data = get_copilot_token(github_token)
copilot_token_cache["token"] = token_data["token"]
copilot_token_cache["expires_at"] = token_data["expires_at"]
# Start background refresh
start_token_refresh_daemon(github_token)
# Demonstration
print("ð¤ Calling Copilot LLM...")
answer = call_copilot_llm("What is GitHub Copilot?")
print(f"\nð¤ Copilot says:\n{answer}")
# Keep main thread alive to see refreshes if needed
print("\n(Script will stay active for 2 minutes to show refresh logic...)")
time.sleep(120)
except KeyboardInterrupt:
print("\nð Exiting...")
if __name__ == "__main__":
main()
æ¤å®ç°å æ¬ï¼
- Device Flow 认è¯ï¼ä½¿ç¨ GitHub CLI Client ID è·å OAuth tokenã
- æä¹
åï¼å° GitHub token ä¿åå°
~/.copilot_github_tokenï¼å¹¶è®¾ç½®åéæéã - 线ç¨å·æ°ï¼å®ææ´æ°çæç Copilot ä¼è¯ tokenï¼éå¸¸å¨ 25-30 åéåè¿æï¼ã
- LLM éæï¼ä¸ä¸ªå¯å·¥ä½ç
call_copilot_llm彿°ï¼ä½¿ç¨ Copilot API æéç VS Code editor headersã
æ¨å¯ä»¥è¿è¡æ¤èæ¬è¿è¡è®¤è¯ï¼å¹¶å¨ CLI åºç¨ç¨åºä¸ä½¿ç¨ Copilotã
æèï¼
[REDACTED]
